diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d44d8a2..031703d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -25,7 +25,7 @@ The site is everything under `source/`. Most of it is written here, but two file | `/helm-charts/` (the Helm chart repository) | the chart packages of the `ansibleforms/helm-charts` releases, indexed at build time | the `helm-charts` repository | | everything else in `source/` | this repository | here | -The docs are served under a language prefix (`/en/`, `/es/`), and the language selector in the header lists +The docs are served under a language prefix, its ISO 639-1 code (`/en/`, `/es/`, `/de/`...), and the language selector in the header lists every language in `docs_languages` (`source/_config.yml`). Every page that used to live at the root keeps its address as a redirect, written at build time by `scripts/redirects.sh`, to the reader's language: the one they last picked, else their browser's, else English. The install script (`/install`) and the Helm chart diff --git a/README.md b/README.md index 260b4ad..867958d 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ The site covers everything a user of AnsibleForms needs, from the first install - The app's changelog, rebuilt into the site on every release - The Helm chart repository, served under `/helm-charts/` - The 6.x documentation, kept alongside under `/v6/` -- The docs in English and Spanish under `/en/` and `/es/`, picked from the reader's browser language +- The docs in the app's eleven languages, each under its ISO 639-1 code (`/en/`, `/es/`, `/fr/`, `/ja/`...), picked from the reader's browser language ## Previewing locally diff --git a/i18n/ca.yml b/i18n/ca.yml new file mode 100644 index 0000000..21ed3d8 --- /dev/null +++ b/i18n/ca.yml @@ -0,0 +1,42 @@ +# The Catalan docs : read after source/_config.yml by scripts/build-language.sh, so only what +# differs from the English site is set here. Jekyll merges the two, nested keys included. + +lang: ca +docs_language: "ca" + +title: "Documentació d'AnsibleForms" +description: "Documentació tècnica d'AnsibleForms" + +footer_content: "Copyright © 2023-2026 AnsibleForms. Tots els drets reservats." + +# "Edit this page on GitHub" opens the Catalan page's source +gh_edit_link_text: "Edita aquesta pàgina a GitHub" +gh_edit_source: i18n/ca + +just_the_docs: + collections: + introduction: + name: "Introducció" + get_started: + name: "Primers passos" + configure: + name: "Configuració" + build_forms: + name: "Creació de formularis" + use: + name: "Guia d'usuari" + integrate: + name: "Integració" + security_assessment: + name: "Seguretat" + reference: + name: "Referència" + +# The version selector (_includes/version_select.html) : a list is replaced, not merged +docs_versions: + - name: "7" + title: "7.x (la més recent)" + url: "/ca/" + - name: "6" + title: "6.x (en anglès)" + url: "/v6/" diff --git a/i18n/ca/_build_forms/expressions/credentials.md b/i18n/ca/_build_forms/expressions/credentials.md new file mode 100644 index 0000000..01ed7dc --- /dev/null +++ b/i18n/ca/_build_forms/expressions/credentials.md @@ -0,0 +1,54 @@ +--- +layout: default +title: Credencials +parent: Expressions +nav_order: 4 +translated_from: bfa50c90495c68300d189f9a0eb38e25df9e7c8e +--- + +# Credencials +{: .no_toc } + +Llegeix una credencial desada en una expressió +{: .fs-6 .fw-300 } + +--- + +Llegeix una credencial desada pel nom o per una expressió regular, amb una alternativa: + +```javascript +fn.fnCredentials('credentialname_or_regex','fallback_credentialname_or_regex') + +// Try to use `fnRestBasic` and `fnRestJwtSecure` if possible, this avoids passwords and tokens going over the network. + +// output : a credential object with all properties (user, password, host, port) +``` + +Primer es prova el nom exacte. Si cap credencial no té aquest nom, el nom s'utilitza com a expressió regular i després es prova l'alternativa. + +#### Limitat per rol + +Quan un dels rols de l'usuari inclou `credentials` a `config.yaml`, `fn.fnCredentials` només retorna una credencial que aquest rol +permeti: els patrons del rol es comparen amb el nom de la credencial trobada (pel nom, per expressió regular o per l'alternativa), +i qualsevol altra es rebutja. Els rols sense la llista no la limiten, i un administrador no està mai limitat. + +#### Credencials d'un magatzem de secrets + +Una credencial que indica un [magatzem de secrets](../secret-stores) obté el seu `user` i el seu `password` +d'aquest magatzem en temps d'execució. `fn.fnCredentials('myapp')` continua funcionant sense canvis. + +Un secret també es pot llegir sense cap fila de credencial, allà on s'accepti un nom de credencial +(inclosos `fnRestBasic`, `fnRestJwtSecure` i les substitucions de capçaleres de `fnRestAdvanced`): + +```javascript +fn.fnCredentials('secret:vault:secret/ontap') // secret:: +fn.fnCredentials('vault:secret/ontap') // the store named `vault` +``` + +Les claus del secret s'assignen tal com es descriu a [Noms de clau](../secret-stores#key-names). +Un secret amb una altra forma es transforma amb una expressió `jq` com a tercer argument: + +```javascript +// secret: { "creds": { "u": "admin", "p": "Netapp12" } } +fn.fnCredentials('vault:secret/weird','','.creds | { user: .u, password: .p }') +``` diff --git a/i18n/ca/_build_forms/expressions/index.md b/i18n/ca/_build_forms/expressions/index.md new file mode 100644 index 0000000..91088ff --- /dev/null +++ b/i18n/ca/_build_forms/expressions/index.md @@ -0,0 +1,76 @@ +--- +layout: default +title: Expressions +nav_order: 1 +has_children: true +has_toc: false +permalink: /expressions/ +translated_from: 52d74e32540fba4dfa5078c8976147b39a2ad2cf +--- + +# Expressions +{: .no_toc } + +Calcula els valors dels camps amb JavaScript, al navegador o al servidor +{: .fs-6 .fw-300 } + +--- + +Per als autors de formularis: omple els camps de manera dinàmica amb JavaScript, calculats al navegador o obtinguts al servidor. + +L'atribut `expression` d'un camp de formulari et permet crear formularis dinàmics amb expressions JavaScript. + +--- + +## Introducció + +L'atribut `expression` està disponible en diversos tipus de camp: +- camp `enum`: per omplir les opcions del desplegable de manera dinàmica +- camp `expression`: per obtenir o generar qualsevol tipus de dades +- camp `html`: per construir-ne el contingut HTML +- camps `yaml` i `list`: per omplir-ne les dades + +Les expressions JavaScript s'avaluen al **costat del servidor** (per defecte) o al **costat del client**, segons el que indiqui la propietat del camp `runLocal`. +Un camp `html`, i els tipus de camp `local`, `local_out` i `credential`, sempre executen la seva expressió al navegador, digui el que digui +`runLocal`. + +- **Al costat del servidor** (`runLocal: false`, el valor per defecte): funcions predefinides que obtenen dades d'API, fitxers i bases de dades. +- **Al costat del client** (`runLocal: true`): el codi aprofita tot el motor JavaScript dins de l'entorn aïllat del navegador per fer càlculs, transformacions i manipulacions. + +--- + +## Qüestions de seguretat + +Com que les expressions s'avaluen amb la funció `eval` de JavaScript, la injecció de codi és un risc potencial: + +- **Les expressions del costat del servidor** passen primer per un sanejador: cada crida ha de ser una funció `fn.` o `fnc.`, i es rebutgen les línies múltiples, + el `;`, les plantilles literals, `process.env` i les maneres de sortir d'`eval` (`import`, `require`, `constructor`, ...). +- **Les expressions del costat del client** s'avaluen dins de l'entorn aïllat del navegador i es poden considerar segures. + +El nivell d'exigència del sanejador depèn de +[`EXPRESSION_SANITIZER`](../customization/security.html#env_EXPRESSION_SANITIZER): + +| Valor | Expressions del costat del servidor | +|---|---| +| `strict` (per defecte) | crides `fn.` i `fnc.`, i mètodes sobre el seu resultat, com ara `fn.fnTime().format('YYYY')` | +| `paranoid` | només crides directes `fn.` i `fnc.`, sense mètodes sobre el seu resultat | +| `off` | es rebutgen totes les expressions del costat del servidor; només funcionen les expressions `runLocal` | +| `legacy` | les regles de la 6.2.1, que permeten a qualsevol usuari autenticat executar codi al servidor; només per a una actualització, i només a l'entorn real (no des de la pàgina de configuració) | + +Un valor buit o desconegut equival a `strict`. Un canvi s'aplica a la següent expressió, sense reiniciar. + +--- + +## En aquesta secció + +Cada tema té la seva pròpia pàgina: + +| Pàgina | Què tracta | +|---|---| +| [Marcadors](placeholders.html) | Fer referència a un altre camp, a una constant o a l'usuari amb `$(...)` | +| [Expressions locals](local.html) | JavaScript que s'executa dins de l'entorn aïllat del navegador | +| [Expressions remotes](remote.html) | Funcions del costat del servidor per a dates, xarxes, fitxers, SSH i noms numerats | +| [API REST](rest-apis.html) | Cridar API REST amb autenticació bàsica, per token o personalitzada | +| [Credencials](credentials.html) | Llegir una credencial desada | +| [Ordenació](sorting.html) | Ordenar matrius amb un objecte d'ordenació | +| [Consultes jq](jq.html) | Transformar dades amb jq | diff --git a/i18n/ca/_build_forms/expressions/jq.md b/i18n/ca/_build_forms/expressions/jq.md new file mode 100644 index 0000000..7484645 --- /dev/null +++ b/i18n/ca/_build_forms/expressions/jq.md @@ -0,0 +1,59 @@ +--- +layout: default +title: Consultes jq +parent: Expressions +nav_order: 6 +translated_from: b34dbbec6c5d115f9bb41450962c3fce9606035f +--- + +# Consultes jq +{: .no_toc } + +Transforma dades amb jq, incloses les funcions integrades +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +## Executar una consulta JSON (jq) sobre un objecte + +Transforma un objecte, per exemple el valor d'un altre camp, amb una expressió jq: + +```javascript +fn.fnJq($(settings),'.mapping | keys') + +// output : a full json object taken from another field called "settings", converted by jq + +// fn.fnJq(object, jq) +// - object, for example read from rest or yaml file +// - jq-expression : a jq-expression (https://jqplay.org) +// - wrap the result in fn.fnSort to order it +``` + +A partir de la 7.3.0, un filtre jq s'executa com a màxim [`JQ_TIMEOUT_SECONDS`](../customization/security.html#env_JQ_TIMEOUT_SECONDS) (30 per defecte) +abans d'aturar-se, i la seva sortida es limita a 64 MB. Això s'aplica a `fn.fnJq` i a l'expressió jq de les funcions de REST, de fitxer, +de credencial i de consulta a base de dades. + +--- + +## Funcions JQ integrades + +Totes les funcions que obtenen dades accepten una consulta JSON (jq), un llenguatge per manipular objectes i matrius de dades. +Quan manipules dades, potser necessites convertir bytes a KB, MB o GB, o arrodonir nombres. +Per a això, AnsibleForms inclou unes quantes funcions jq pròpies: + +- **fn2KB**: de bytes a KB +- **fn2MB**: de bytes a MB +- **fn2GB**: de bytes a GB +- **fnRound0**: arrodoneix amb 0 decimals +- **fnRound1**: arrodoneix amb 1 decimal +- **fnRound2**: arrodoneix amb 2 decimals +- **fnRound**: arrodoneix amb 2 decimals + +```javascript +fn.fnRestBasic('get','https://youruri','','CREDS', + '[.records[] | {"Available Capacity":.storage_capacity.available | fn2GB | fnRound }]') +// note you need to pipe into the functions +``` diff --git a/i18n/ca/_build_forms/expressions/local.md b/i18n/ca/_build_forms/expressions/local.md new file mode 100644 index 0000000..1527a3e --- /dev/null +++ b/i18n/ca/_build_forms/expressions/local.md @@ -0,0 +1,232 @@ +--- +layout: default +title: Expressions locals +parent: Expressions +nav_order: 1 +translated_from: 77a88157a129701065cf770bf1005b4391140aa1 +--- + +# Expressions locals +{: .no_toc } + +JavaScript que s'executa dins de l'entorn aïllat del navegador +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +Els exemples següents s'executen amb la propietat del camp `runLocal: true`. +S'executen dins de l'entorn aïllat del navegador i poden aprofitar tot el motor JavaScript. + +{: .note } +> **Consell**: fes servir el tipus `local` com a àlies de `type: expression, runLocal: true, hide: true, output: false` +> **Consell**: fes servir el tipus `local_out` com a àlies de `type: expression, runLocal: true, hide: true` + +--- + +## Convenció de noms + +Fes servir manipulacions de cadenes per aplicar convencions de noms. + +```javascript +'$(field1) $(field2)'.replace('-','_').toUpperCase() +``` + +--- + +## Càlcul + +Fes servir les matemàtiques per fer càlculs. + +```javascript +Math.round($(field1)*$(field2)*Math.PI) // Math.round and Math.PI are native javascript +``` + +--- + +## Conversions + +Converteix bytes a gigabytes. + +```javascript +($(size_bytes)/1024/1024/1024).toFixed(2) // toFixed is native javascript method +``` + +--- + +## Convertir una matriu d'objectes en una taula HTML + +Converteix una matriu d'objectes, per exemple d'un altre camp, en una taula HTML per a un camp `html`: + +```javascript +fnToTable($(my_array_field),{ + tableClass: '', + escapeHtml: true, + emptyCell: '', + includeHeader: true +}) + +// output : an html-table representation of the array of objects taken from another field called "my_array_field" +// tip : add tableClass: 'table table-striped table-bordered' for bootstrap styling +``` + +--- + +## Obtenir un nom amb numeració incremental + +Amb la numeració automàtica, potser necessites trobar el nom següent en una matriu de cadenes numerades. +Aquesta funció també està disponible com a expressió del costat del servidor (amb el prefix `fn.`). + +```javascript +fnGetNumberedName(['server001','server002','server005'],'server###','server001',false) +// result : "server006" + +fnGetNumberedName(['server001','server002','server005'],'server###','server001',true) +// result : "server003" + +fnGetNumberedName($(fieldlist),'server###','server001',true) +// use another expression field as input for the array + +// fnGetNumberedName(array,pattern,default,fillgaps) +// This function searches for a numbered pattern in a list of string, +// increases the highest number and returns a name like the pattern +// - array : an array object, you can use a placeholder to an expression where you know it's an array +// - pattern : a string that hold the # as a digit +// - default : if no value is found, return this default +// - fillgaps : a boolean to indicate it can fill gaps in the numbers, 1,2,3,6 => 4 +``` + +Quan el primer argument no és una matriu, la funció local retorna el valor per defecte. La funció de servidor `fn.fnGetNumberedName` +falla amb un error. + +--- + +## Manipulació de matrius d'objectes + +Sovint cal filtrar, modificar i ordenar matrius d'objectes. +AnsibleForms inclou una eina auxiliar pròpia que manté aquest codi concís. + +```javascript +/* + fnArray.from($(your_array_field)) // custom helper library + .filterBy({property1:'value1',property2:'value2', ...}) // filters by property value (a string, * wildcards allowed) + .regexBy({property1:'regex1',property2:'regex2', ...}) // filters the array by property matched against regex + .distinctBy('property1','property2', ...) // will make the array entries unique by property + .selectAttr({prop1:'property1',prop2:'property2'}) // only selects a certain property, and you can relabel them + .sortBy('property1','-property2', ...) // will order the array. To have descending add a "-" (minus) before the property + + mylist: + [ + { + name:'Spiderman', + has_ability: true, + ability: 'Can do whatever a spider can' + }, + { + name:'Superman', + has_ability: true, + ability: 'Superstrong,Flying,Laserbeams' + }, + { + name:'FamilyGuy', + has_ability: false + }, + { + name:'Wolverine', + has_ability: true, + ability: 'Enhanced healing' + } + ] +*/ + +fnArray.from($(mylist)) // take data from another field 'mylist' +.regexBy({name:'.*man$'}) // name must end with 'man' +.filterBy({has_ability:'true'}) // must have abilities (a string: 'true', not true) +.selectAttr({name:'name',ability:'ability'}) // only take properties name and ability +.sortBy('-name') // sort by name descending + +/* + result : + [ + {name:'Superman',ability:'Superstrong,Flying,Laserbeams'}, + {name:'Spiderman',ability:'Can do whatever a spider can'} + ] +*/ +``` + +--- + +## Manipulació de matrius d'objectes amb JavaScript pur + +Tots els mètodes estàndard de matrius de JavaScript continuen disponibles per filtrar i modificar les teves dades, com ara `map`, `forEach`, `find`, `filter` i `reduce`. + +```javascript +// source : https://medium.com/@jeff_long/understanding-foreach-map-filter-and-find-in-javascript-f91da93b9f2c + +mylist= + [ + { + name:'Bob', + age: 5 + }, + { + name:'Tom', + age: 10 + }, + { + name:'Paul', + age: 30 + }, + { + name:'Tom', + age: 40 + } + ] + +// simple filter +$(mylist).filter((x) => x.age<=20) // filter age<=20 +/* result: +[ + {name:'Bob',age:5}, + {name:'Tom',age:10} +] +*/ + +// filter and addition +$(mylist) + .filter((x) => x.age<=20) // filter age<=20 + .map((x) => { return {...x,diff:20-x.age} }) // add new property diff +/* result: +[ + {name:'Bob',age:5,diff:15}, + {name:'Tom',age:10,diff:10} +] +*/ + +// find +$(mylist).find((x) => x.name=='Tom').age // find age of first Tom +// result: 10 + +// make sum with reduce +$(mylist).reduce((sum,x) => sum+x.age,0) // calculate sum of ages +// result: 85 + +// make temp function +((arr,min)=>{ + return arr + .filter(x => x.age>=min) // filter + .map(x => { + var preview=`${x.name} (${x.age})`; // make preview string + return {...x,preview:preview} }) // add new preview property +})($(mylist),20) // feed function with mylist and 20 +/* result: +[ + {name:'Paul',age:30,preview:'Paul (30)'}, + {name:'Tom',age:40,preview:'Tom (40)'} +] +*/ +``` + +--- diff --git a/i18n/ca/_build_forms/expressions/placeholders.md b/i18n/ca/_build_forms/expressions/placeholders.md new file mode 100644 index 0000000..4505038 --- /dev/null +++ b/i18n/ca/_build_forms/expressions/placeholders.md @@ -0,0 +1,123 @@ +--- +layout: default +title: Marcadors +parent: Expressions +nav_order: 0.5 +translated_from: bd63e437a4f77c707a1bf8d8ee99b1516063b62a +--- + +# Marcadors +{: .no_toc } + +Fes referència a un altre camp, a una constant o a l'usuari actual amb `$(...)` +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +## Què és un marcador + +Un marcador és una referència escrita com a `$(reference)`. Se substitueix per un valor abans que s'utilitzi el text que el conté. + +Els marcadors funcionen a l'`expression`, la `query` i el `default` d'un camp (aquest últim avaluat amb `evalDefault`), i també al seu `label`, +`help` i `placeholder`. Un camp que conté un marcador depèn del camp que anomena: espera fins que aquest camp tingui un +valor, i es torna a avaluar cada vegada que aquest valor canvia. Així es construeixen els desplegables en cascada. + +```yaml +- name: city + type: enum + values: [Amsterdam, Brussels] +- name: datacenter + type: enum + dbConfig: { name: CMDB, type: mysql } + query: select name from cmdb.datacenter where city='$(city)' +``` + +--- + +## A què pot fer referència un marcador + +Un marcador anomena un camp del formulari, o un d'aquests, que tenen tots els formularis: + +| Referència | Què conté | +|---|---| +| `$(field)` | el valor d'un altre camp del formulari | +| `$(name)`, una constant | una [constant](../config/constants.html) de `config.yaml`, o un valor dels `varsFiles` del formulari | +| `$(__user__)` | l'usuari que ha iniciat la sessió: `username`, `type`, `groups`, `roles` | +| `$(__parent__.field)` | en un [subformulari](../forms/subform.html) (una fila d'una llista, un pas d'un assistent), un valor del formulari pare | + +```yaml +expression: "'$(__user__.username)'" +expression: $(__user__.groups) +``` + +--- + +## Accedir a una part d'un valor + +La notació de punt i d'índex llegeix una part d'un valor, sempre que el camí només contingui lletres, dígits, `_`, `-`, `.` i `[n]`: + +| Marcador | Sobre | Dona | +|---|---|---| +| `$(field)` | un camp de text, de número o de contrasenya | el valor | +| `$(field)` | un enum de registres | la `placeholderColumn` del registre seleccionat, o si no la seva primera columna | +| `$(field.col)` | un enum de registres | aquesta columna del registre seleccionat | +| `$(field)` | un enum amb `multiple: true` | la columna triada de cada registre seleccionat, com a matriu | +| `$(field)` | una expressió, una llista o una constant | el valor sencer (una llista dona les seves files) | +| `$(field.a.b)`, `$(f[0].x)` | una expressió, una llista o una constant | aquesta part de l'objecte o de la matriu | + +Posar `placeholderColumn: "*"` en un enum fa que `$(field)` doni tot el registre seleccionat en lloc d'una sola columna. + +```yaml +- name: city + type: enum + dbConfig: { name: CMDB, type: mysql } + query: select id, name from cmdb.city + valueColumn: name + placeholderColumn: id # $(city) gives the id; $(city.name) still gives the name +- name: servers + type: expression + expression: "[{name: 'web1'}, {name: 'web2'}]" + runLocal: true +- name: first_server + type: expression + expression: $(servers[0].name) # 'web1' + runLocal: true +``` + +--- + +## Com s'insereix el valor + +La manera com s'insereix un valor al text depèn d'on es troba el marcador. + +| On | Exemple | Es converteix en | +|---|---|---| +| una expressió, fora de cometes | `$(count) + 1` | un literal JavaScript: un número continua sent un número, un text es converteix en una cadena entre cometes, un objecte o una matriu en un literal | +| una expressió, tota una cadena entre cometes | `fn.fnLs('$(dir)')` | el mateix literal, cometes incloses, de manera que un valor amb una cometa no se'n pot escapar | +| una expressió, dins d'una cadena més llarga | `'$(dir)/vars'` | el text, escapat per a aquesta cadena | +| una consulta, una etiqueta, un text d'ajuda | `where city='$(city)'` | el text | + +Un camp els marcadors del qual encara no es poden resoldre tots no s'avalua; amb `ignoreIncomplete: true`, un valor que falta +s'insereix com a `undefined`. + +### Accents greus i `${` en un valor + +A partir de la 7.3.0, el valor d'un camp no es pot executar com a codi quan el servidor l'insereix en una expressió (expressions remotes, validació +del llançament, MCP i xat). Un accent greu o un `${` al valor s'escriu com una seqüència d'escapament Unicode (```, `${`), de manera que continua sent +text fins i tot dins d'una plantilla literal. Les expressions del costat del servidor rebutgen del tot les plantilles literals; per a això fes servir `runLocal`. + +Una expressió `runLocal` avaluada al navegador insereix el valor tal com indica la taula anterior, sense aquest escapament, així que no posis +un marcador dins d'una plantilla literal en aquest cas. + +--- + +## Vegeu també + +Pàgines relacionades i entrades de les PMF: + +- [Expressions locals](local.html) i [Expressions remotes](remote.html): on s'utilitzen la majoria dels marcadors +- [PMF: Desplegables en cascada](../faq.html#cascaded-dropdowns) i [Marcadors de camp](../faq.html#field-placeholders): més exemples +- [PMF: Com accedeixo a les dades del formulari pare des d'un subformulari?](../faq.html#how-do-i-access-parent-form-data-inside-a-subform) diff --git a/i18n/ca/_build_forms/expressions/remote.md b/i18n/ca/_build_forms/expressions/remote.md new file mode 100644 index 0000000..b05eb5e --- /dev/null +++ b/i18n/ca/_build_forms/expressions/remote.md @@ -0,0 +1,252 @@ +--- +layout: default +title: Expressions remotes +parent: Expressions +nav_order: 2 +translated_from: 8d0f7560216da4a428e1935ac2b6de7b5428c243 +--- + +# Expressions remotes +{: .no_toc } + +Funcions del costat del servidor per a dates, xarxes, fitxers, SSH i noms numerats +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +Els exemples següents s'executen amb la propietat del camp `runLocal: false` (per defecte). +S'avaluen al costat del servidor. + +Com que avaluar codi al servidor és un risc de seguretat, l'expressió se saneja i es limita a les funcions que +porta AnsibleForms i a les [funcions que hi afegeixis tu](#your-own-functions). +Les expressions del costat del servidor estan pensades per obtenir informació de fonts de dades com ara fitxers, API REST i ordres SSH. + +{: .important } +Les funcions integrades del costat del servidor porten el prefix `fn.` (per exemple, `fn.fnRestBasic`), i les teves, el prefix `fnc.`. + +--- + +## Manipular la data i l'hora + +Treballa amb dates i hores mitjançant [Day.js](https://day.js.org): + +```javascript +fn.fnTime().diff(fn.fnTime('2019-10-01'),'day') // number of days between now and 2019-10-01 + +// This is the core implementation of https://day.js.org +``` + +--- + +## Obtenir la informació CIDR d'una IP + +Obtén la subxarxa d'una adreça IP i d'una màscara de xarxa, i comprova quines adreces en formen part: + +```javascript +fn.fnCidr('172.16.0.1','255.255.0.0') + +// fn.fnCidr(ip,netmask) +// - ip : an ip address +// - netmask : a netmask +// +// it will return the Cidr subnet information as well as expose a `contains` method to check whether an ip is part of this subnet. +// { +// "networkAddress":"172.16.0.0", +// "firstAddress":"172.16.0.1", +// "lastAddress":"172.16.255.254", +// "broadcastAddress":"172.16.255.255", +// "subnetMask":"255.255.0.0", +// "subnetMaskLength":16, +// "numHosts":65534, +// "length":65536, +// "contains":(ip)=>{return ...} +// } +``` + +--- + +## Obtenir la sortida d'SSH + +Executa una ordre en un amfitrió remot per SSH i fes servir la seva sortida: + +```javascript +fn.fnSsh('root','172.16.0.1','ls -la') + +// fn.fnSsh(user,host,command,jq-expression,timeoutSeconds) +// - user : the ssh user +// - host : the host +// - command : the command to trigger by ssh, as the remote host's shell reads it +// - jq-expression : an optional jq-expression (https://jqplay.org), applied to the output lines +// - timeoutSeconds : an optional time limit, 60 seconds by default; running out of time is an error +// +// it returns the output lines (stdout and stderr) and a last line exit() with the exit code. +// ssh itself is started without a local shell, so the user and host can never become a second local command. +// +// You must use 'known_hosts' and 'public-key' to setup non-interactive password-less authentication. +// In the settings you can find the public-key and add your target-host to known_hosts +``` + +--- + +## Llistar els fitxers d'un directori + +Llista els fitxers d'un directori del servidor d'AnsibleForms, opcionalment de manera recursiva i filtrats: + +```javascript +fn.fnLs('/tmp',{ recursive: true, regex: '.*\\.log$', metadata: true }) + +// fn.fnLs(path,options) +// - path : path to directory +// - options : recursive:boolean, regex:string ,metadata:boolean +// - recursive : whether to list files recursively +// - regex : a regular expression, matched against the path relative to the listed directory +// - metadata : whether to return objects with file metadata (path, name, type, size, created, modified, ...) +// +// directories are always listed too, with a trailing / (such as 'logs/'), and the regex sees that slash as well +``` + +--- + +## Analitzar una pàgina HTML + +Obtén una pàgina HTML i extreu-ne les parts que coincideixen amb una expressió regular: + +```javascript +fn.fnParseHtmlWithRegex('https://ansibleguy.com','(.*?)','g') + +// fn.fnParseHtmlWithRegex(url,regex,flags,credential) +// - url : url to html page +// - regex : a regular expression, groups ( ) are optional +// - flags : regex flags (such as g,i,m), defaults to 'g'; without g only the first match is returned +// - credential : an optional credential name, used for basic authentication +// (a credential without both a user and a password is ignored, the page is fetched without authentication) +// +// it will grab the html source and return an array with one object per match, at most 10000 : +// { fullMatch, groups (the numbered group matches), namedGroups } +``` + +La pàgina s'obté sota [`REST_ALLOWED_HOSTS`](../customization/security.html#env_REST_ALLOWED_HOSTS) i +[`REST_DENIED_HOSTS`](../customization/security.html#env_REST_DENIED_HOSTS), com les funcions REST. A diferència d'aquestes, ignora +`REST_IGNORE_CERTS` i `REST_TIMEOUT_SECONDS`: sempre comprova el certificat i espera com a màxim 30 segons. + +--- + +## Obtenir informació DNS + +Resol un registre DNS d'un domini: + +```javascript +fn.fnDnsResolve('ansibleguy.com','A') + +// fn.fnDnsResolve(fqdn,type) +// - fqdn : a fully qualified domain name +// - type : the type of dns record (A,AAAA,MX,NS,CNAME,TXT,SRV,PTR) +``` + +--- + +## Llegir un fitxer JSON + +Llegeix un fitxer JSON del servidor, opcionalment filtrat amb jq: + +```javascript +fn.fnReadJsonFile('/tmp/file.json','.[].name') + +// fn.fnReadJsonFile(path,jq-expression) +// - path : path to json file +// - jq-expression : an optional jq-expression (https://jqplay.org) +``` + +--- + +## Llegir un fitxer YAML + +Llegeix un fitxer YAML del servidor, opcionalment filtrat amb jq: + +```javascript +fn.fnReadYamlFile('/tmp/file.yaml','.[].name') + +// fn.fnReadYamlFile(path,jq-expression) +// - path : path to yaml file +// - jq-expression : an optional jq-expression (https://jqplay.org) +``` + +--- + +## Obtenir un nom amb numeració incremental + +En una matriu de cadenes amb números incrementals (server001, server002, ...), potser necessites trobar el següent nom disponible. +Aquesta funció també està disponible com a expressió local (sense el prefix `fn.`). + +```javascript +fn.fnGetNumberedName(['server001','server002','server005'],'server###','server001',false) +// result : "server006" + +fn.fnGetNumberedName(['server001','server002','server005'],'server###','server001',true) +// result : "server003" + +fn.fnGetNumberedName($(fieldlist),'server###','server001',true) +// use another expression field as input for the array + +// fn.fnGetNumberedName(array,pattern,default,fillgaps) +// This function searches for a numbered pattern in a list of string, +// increases the highest number and returns a name like the pattern +// - array : an array object, you can use a placeholder to an expression where you know it's an array +// - pattern : a string that hold the # as a digit +// - default : if no value is found, return this default +// - fillgaps : a boolean to indicate it can fill gaps in the numbers, 1,2,3,6 => 4 +``` + +Al servidor, `fn.fnGetNumberedName` falla amb un error quan el primer argument no és una matriu. L'expressió local +(sense `fn.`) retorna el valor per defecte. + +--- + +## Les teves pròpies funcions + +Afegeix funcions JavaScript pròpies a `custom.js` i crida-les en una expressió de servidor amb el prefix `fnc.`. + +El fitxer exporta un objecte de funcions. El que porta la imatge conté dos exemples: + +```javascript +import logger from "../lib/logger.js"; + +const fnSum = function(a,b) { + logger.debug("[fnSum] sum is happening") + return a+b +}; +const fnMultiply = function(a,b) { + logger.debug("[fnMultiply] multiply is happening") + return a*b +}; + +export default { + fnSum, + fnMultiply +}; +``` + +```yaml +- name: total + type: expression + expression: fnc.fnSum($(disk_count), 10) +``` + +De la mateixa manera, `jq.custom.definitions` conté definicions jq pròpies. S'afegeixen al davant de cada consulta jq que +executa el servidor, de manera que les [consultes jq](jq.html) de qualsevol funció les poden fer servir. + +En un contenidor, munta tots dos fitxers per sobre dels de la imatge i reinicia; es llegeixen quan s'inicia el servidor: + +```yaml +volumes: + - ./data/functions/custom.js:/app/dist/src/functions/custom.js + - ./data/functions/jq.custom.definitions:/app/dist/src/functions/jq.custom.definitions +``` + +{: .warning } +> Una funció personalitzada s'executa dins del procés del servidor, amb els seus permisos, cada vegada que una expressió la crida. El +> [sanejador](index.html#security-concerns) comprova que l'expressió només cridi funcions `fn.` i `fnc.`; el que una +> funció fa amb els seus arguments és cosa teva. diff --git a/i18n/ca/_build_forms/expressions/rest-apis.md b/i18n/ca/_build_forms/expressions/rest-apis.md new file mode 100644 index 0000000..9bc3ed6 --- /dev/null +++ b/i18n/ca/_build_forms/expressions/rest-apis.md @@ -0,0 +1,158 @@ +--- +layout: default +title: API REST +parent: Expressions +nav_order: 3 +translated_from: e4ceac62125b53a88d479bf7f2a0e7230edce2b2 +--- + +# API REST +{: .no_toc } + +Crida API REST amb autenticació bàsica, per token o personalitzada +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +## API REST amb autenticació bàsica + +Crida una API REST amb l'usuari i la contrasenya d'una credencial desada: + +```javascript +fn.fnRestBasic( + 'get', + 'https://resturl/api/', + '', + 'name_of_credential_in_database', + '[.records[] | {name:.name, email:.email, spouse:.relations.spouse}]', + 'name', + false +) + +// output : a full json object coming from rest, json transformed with jq, result sorted and transformed by javascript. + +// fn.fnRestBasic(method,url,body,credentialname,jq-expression,sort-object) +// - method : get,post,put,delete +// - url : url to restapi (can for example contain a placeholder like 'https://$(serverfield.fqdn)/api/' +// - body : in case of post and put +// - credential-name : it will lookup the credentials as you have saved in the gui +// - jq-expression : an optional jq-expression (https://jqplay.org) +// - sort object : a sort object to order the result +// - hasBigInt : a boolean indicating if it should convert Int64 to string +``` + +--- + +## API REST amb autenticació per token + +Crida una API REST amb un token bearer escrit a l'expressió: + +```javascript +fn.fnRestJwt( + 'get', + 'https://resturl/api/', + '', + 'your_jwt_token_in_text', + '[.records[] | {name:.name, age:.age}]', + ['age','name'], + false +) + +// output : a full json object coming from rest, json transformed with jq, result sorted, first by age, then by name + +// fn.fnRestJwt(method,url,body,token,jq-expression,sort-object) +// - method : get,post,put,delete +// - url : url to restapi (can for example contain a placeholder like 'https://$(serverfield.fqdn)/api/' +// - body : in case of post and put +// - token : it will be add as a Bearer Authorization header +// - jq-expression : an optional jq-expression (https://jqplay.org) +// - sort-object : a sort object to sort the result +// - hasBigInt : a boolean indicating if it should convert Int64 to string +// - tokenPrefix : a prefix, defaults to 'Bearer' (v5.0.0) +``` + +--- + +## API REST amb autenticació per token segura + +Crida una API REST amb un token bearer tret d'una credencial desada, de manera que no apareix mai al formulari: + +```javascript +fn.fnRestJwtSecure( + 'get', + 'https://resturl/api/', + '', + 'name_of_credential_in_database', + '[.records[] | {name:.name, age:.age}]', + ['age','name'], + false +) + +// output : a full json object coming from rest, json transformed with jq, result sorted, first by age, then by name + +// fn.fnRestJwtSecure(method,url,body,token,jq-expression,sort-object) +// - method : get,post,put,delete +// - url : url to restapi (can for example contain a placeholder like 'https://$(serverfield.fqdn)/api/' +// - body : in case of post and put +// - credential_name : Encrypted credential will be looked up. The password will be the token. +// - jq-expression : an optional jq-expression (https://jqplay.org) +// - sort-object : a sort object to sort the result +// - hasBigInt : a boolean indicating if it should convert Int64 to string +// - tokenPrefix : a prefix, defaults to 'Bearer' (v5.0.0) +``` + +--- + +## API REST amb capçaleres personalitzades + +Crida una API REST amb capçaleres pròpies, per a qualsevol altre tipus d'autenticació: + +```javascript +fn.fnRestAdvanced( + 'get', + 'https://resturl/api/', + '', + {'a_custom_http_header':'your_value','Authorization':'basic base64(my_rest_credential)'}, + '.records[].name', + {name:{ignoreCase:true,direction:'desc'}}, + false, + false +) + +// output : a full json object coming from rest, json transformed with jq, result sorted descending by name + +// fn.fnRestAdvanced(method,url,body,{myheader:'value'},jq-expression,sort-object) +// - method : get,post,put,delete +// - url : url to restapi (can for example contain a placeholder like 'https://$(serverfield.fqdn)/api/' +// - body : in case of post and put +// - headers: an object of headers +// - jq-expression : an optional jq-expression (https://jqplay.org) +// - sort-object : a sorting object to order the results +// - hasBigInt : a boolean indicating if it should convert Int64 to string +// - raw : return data and response_headers + +// 3 function-placeholders are allowed in the headers: +// - base64(credential_name) : will create a base64 encoded "username:password". prefix with "basic" if required +// - username(credential_name) : will add the username of the credential +// - password(credential_name) : will add the password of the credential +``` + +--- + +## Certificats i temps límit + +A partir de la 7.3.0, totes les funcions auxiliars REST (`fnRestBasic`, `fnRestAdvanced`, `fnRestJwt`, `fnRestJwtSecure`) comproven el certificat +TLS del punt final i deixen d'esperar passat un temps determinat: + +| Opció | Què canvia | +|---|---| +| [`REST_IGNORE_CERTS`](../customization/security.html#env_REST_IGNORE_CERTS) | `1` omet la comprovació del certificat. Fins a la 7.2.0 no es comprovava mai; deixa-ho a `0` i, en lloc d'això, confia en una CA privada amb `NODE_EXTRA_CA_CERTS` | +| [`REST_TIMEOUT_SECONDS`](../customization/security.html#env_REST_TIMEOUT_SECONDS) | Quant de temps espera una crida una resposta, 60 segons per defecte; així, un punt final que no respon mai fa fallar el camp en lloc de deixar-lo bloquejat | + +A partir de la 7.3.0, un camp el punt final del qual té un certificat autosignat falla amb un error de certificat fins que es defineix una de les dues opcions. +[Crides REST i jq](../customization/security.html#rest-calls-and-jq) descriu totes dues, i com confiar en una CA privada per a totes les crides REST alhora. +[`fn.fnParseHtmlWithRegex`](remote.html#parse-html-page) no és una funció auxiliar REST: ignora totes dues opcions, sempre comprova el +certificat i espera com a màxim 30 segons. diff --git a/i18n/ca/_build_forms/expressions/sorting.md b/i18n/ca/_build_forms/expressions/sorting.md new file mode 100644 index 0000000..51f37af --- /dev/null +++ b/i18n/ca/_build_forms/expressions/sorting.md @@ -0,0 +1,51 @@ +--- +layout: default +title: Ordenació +parent: Expressions +nav_order: 5 +translated_from: 56b0801754aa08a0a6c4941b373bb43d10982b98 +--- + +# Ordenació +{: .no_toc } + +Ordena matrius amb un objecte d'ordenació +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +## Ordenar una matriu + +Ordena una matriu que ve d'una expressió, d'una API REST o d'una base de dades amb un objecte d'ordenació: + +```javascript +fn.fnSort(['a','b','z','q','c'],{'':{direction:'asc'}}) + +// output : sorts the flat array + +// fn.fnSort(arrayinput,sort-object) +// - array, coming from expression or rest or database +// - sort-object : a sorting object to order the results +``` + +--- + +## L'objecte d'ordenació + +Les funcions REST (`fn.fnRestBasic`, `fn.fnRestAdvanced`, `fn.fnRestJwt`, `fn.fnRestJwtSecure`) accepten aquest objecte d'ordenació +com a argument. Per a qualsevol altre resultat, com ara `fn.fnJq` o la lectura d'un fitxer, embolcalla'l amb `fn.fnSort`. + +```javascript +// The sorting object can have multiple forms, for example : + +'name' // will sort ascending on property name +['name','email'] // will first sort on name, then on email +{name:{direction:'desc'}} // will sort on name descending +{name:{ignoreCase:true}} // will sort on name ascending, ignoring case +['name',{email:{ignoreCase:true,direction:'asc'}}] // will sort on name first, then on email, ignoring case +{'':{}} // a special case for sorting a flat array which has no headername (properties) +{'':{direction:'desc'}} // sort a flat array descending +``` diff --git a/i18n/ca/_build_forms/formfields/checkbox.md b/i18n/ca/_build_forms/formfields/checkbox.md new file mode 100644 index 0000000..6ea8817 --- /dev/null +++ b/i18n/ca/_build_forms/formfields/checkbox.md @@ -0,0 +1,131 @@ +--- +layout: default +title: Checkbox +parent: Camps de formulari +nav_order: 8 +translated_from: 6dac54ad9b2bf8aed718b116f4a9d9be4a8184e6 +--- + +# Camp Checkbox +{: .no_toc } + +Un valor cert o fals, per activar una opció o marcar un indicador +{: .fs-6 .fw-300 } + +--- + +## Propietats + +Les propietats disponibles per a un camp `checkbox`, agrupades per finalitat: + +{% assign help = site.data.help %} +{% assign formsyaml = help | where: "link", "forms" | first %} +{% assign form_object = formsyaml.help | where: "name", "Form" | first %} +{% assign formfield_object = form_object.help | where: "name", "Formfield" | first %} + +{%- if formfield_object and formfield_object.items %} + + + + + + + + + + {% assign groups = formfield_object.items | map: "group" | compact | uniq | sort_natural %} + {% for group in groups %} + {% assign group_properties = formfield_object.items | where: "group", group %} + + + + {% for var in group_properties %} + {%- assign item_types = var.with_types | split: ", " %} + {%- assign type_match = false %} + {%- if var.with_types %} + {%- if item_types contains "checkbox" %} + {%- assign type_match = true %} + {%- endif %} + {%- else %} + {%- assign type_match = true %} + {%- endif %} + {%- if type_match %} + + + + + {%- endif %} + {% endfor %} + {% endfor %} + +
AtributComentaris
+ {{ group }} +
+ {{ var.name }}
+ {{ var.type }} + {% if var.required==true %} / obligatori{% endif %} + {% if var.unique==true %} / únic{% endif %} +
+ {% if var.version %}afegit a la versió {{ var.version }}{% endif %} +
+

+ {{ var.short }}
+ {% if var.allowed != nil %} + {{ var.allowed }} + {% endif %} +

+

+ {{ var.description | markdownify }} +

+ {% if var.name == "type" %} +
+ Valor:
+ {{ page.title | downcase }} +
+ {% elsif var.choices.size > 0 %} +
+ Opcions:
+
    + {% for c in var.choices %} +
  • + {% if c.name == var.default %} + {{ c.name }} (per defecte) + {% else %} + {{ c.name }} + {% endif %} +
  • + {% endfor %} +
+
+ {% elsif var.default != nil %} +
+ Per defecte:
+ {{ var.default }} +
+ {% endif %} +
+ +--- + +## Exemples + +Exemples de camps `checkbox`, en YAML: + +{%- assign type_choice = formfield_object.items | where: "name", "type" | first %} +{%- if type_choice.choices %} + {%- assign checkbox_type = type_choice.choices | where: "name", "checkbox" | first %} + {%- if checkbox_type.examples %} + {%- for example in checkbox_type.examples %} + +### {{ example.name }} + +{% if example.description %}{{ example.description | markdownify }}{% elsif example.short %}{{ example.short }}{% else %}La definició del camp, en YAML:{% endif %} + +```yaml +{{ example.code }} +``` + {%- endfor %} + {%- endif %} +{%- endif %} + +{%- endif %} diff --git a/i18n/ca/_build_forms/formfields/datetime.md b/i18n/ca/_build_forms/formfields/datetime.md new file mode 100644 index 0000000..61b1b1e --- /dev/null +++ b/i18n/ca/_build_forms/formfields/datetime.md @@ -0,0 +1,131 @@ +--- +layout: default +title: Datetime +parent: Camps de formulari +nav_order: 3 +translated_from: be604f929c562ff048c03f1c17e1201a053179b4 +--- + +# Camp Datetime +{: .no_toc } + +Un selector de data, hora, setmana, mes o any +{: .fs-6 .fw-300 } + +--- + +## Propietats + +Les propietats disponibles per a un camp `datetime`, agrupades per finalitat: + +{% assign help = site.data.help %} +{% assign formsyaml = help | where: "link", "forms" | first %} +{% assign form_object = formsyaml.help | where: "name", "Form" | first %} +{% assign formfield_object = form_object.help | where: "name", "Formfield" | first %} + +{%- if formfield_object and formfield_object.items %} + + + + + + + + + + {% assign groups = formfield_object.items | map: "group" | compact | uniq | sort_natural %} + {% for group in groups %} + {% assign group_properties = formfield_object.items | where: "group", group %} + + + + {% for var in group_properties %} + {%- assign item_types = var.with_types | split: ", " %} + {%- assign type_match = false %} + {%- if var.with_types %} + {%- if item_types contains "datetime" %} + {%- assign type_match = true %} + {%- endif %} + {%- else %} + {%- assign type_match = true %} + {%- endif %} + {%- if type_match %} + + + + + {%- endif %} + {% endfor %} + {% endfor %} + +
AtributComentaris
+ {{ group }} +
+ {{ var.name }}
+ {{ var.type }} + {% if var.required==true %} / obligatori{% endif %} + {% if var.unique==true %} / únic{% endif %} +
+ {% if var.version %}afegit a la versió {{ var.version }}{% endif %} +
+

+ {{ var.short }}
+ {% if var.allowed != nil %} + {{ var.allowed }} + {% endif %} +

+

+ {{ var.description | markdownify }} +

+ {% if var.name == "type" %} +
+ Valor:
+ {{ page.title | downcase }} +
+ {% elsif var.choices.size > 0 %} +
+ Opcions:
+
    + {% for c in var.choices %} +
  • + {% if c.name == var.default %} + {{ c.name }} (per defecte) + {% else %} + {{ c.name }} + {% endif %} +
  • + {% endfor %} +
+
+ {% elsif var.default != nil %} +
+ Per defecte:
+ {{ var.default }} +
+ {% endif %} +
+ +--- + +## Exemples + +Exemples de camps `datetime`, en YAML: + +{%- assign type_choice = formfield_object.items | where: "name", "type" | first %} +{%- if type_choice.choices %} + {%- assign datetime_type = type_choice.choices | where: "name", "datetime" | first %} + {%- if datetime_type.examples %} + {%- for example in datetime_type.examples %} + +### {{ example.name }} + +{% if example.description %}{{ example.description | markdownify }}{% elsif example.short %}{{ example.short }}{% else %}La definició del camp, en YAML:{% endif %} + +```yaml +{{ example.code }} +``` + {%- endfor %} + {%- endif %} +{%- endif %} + +{%- endif %} diff --git a/i18n/ca/_build_forms/formfields/enum.md b/i18n/ca/_build_forms/formfields/enum.md new file mode 100644 index 0000000..162b715 --- /dev/null +++ b/i18n/ca/_build_forms/formfields/enum.md @@ -0,0 +1,131 @@ +--- +layout: default +title: Enum +parent: Camps de formulari +nav_order: 10 +translated_from: 011ba48e2eebc9a26159fdf981d89b86b43de630 +--- + +# Camp Enum +{: .no_toc } + +Un desplegable amb cerca, per a una o diverses opcions +{: .fs-6 .fw-300 } + +--- + +## Propietats + +Les propietats disponibles per a un camp `enum`, agrupades per finalitat: + +{% assign help = site.data.help %} +{% assign formsyaml = help | where: "link", "forms" | first %} +{% assign form_object = formsyaml.help | where: "name", "Form" | first %} +{% assign formfield_object = form_object.help | where: "name", "Formfield" | first %} + +{%- if formfield_object and formfield_object.items %} + + + + + + + + + + {% assign groups = formfield_object.items | map: "group" | compact | uniq | sort_natural %} + {% for group in groups %} + {% assign group_properties = formfield_object.items | where: "group", group %} + + + + {% for var in group_properties %} + {%- assign item_types = var.with_types | split: ", " %} + {%- assign type_match = false %} + {%- if var.with_types %} + {%- if item_types contains "enum" %} + {%- assign type_match = true %} + {%- endif %} + {%- else %} + {%- assign type_match = true %} + {%- endif %} + {%- if type_match %} + + + + + {%- endif %} + {% endfor %} + {% endfor %} + +
AtributComentaris
+ {{ group }} +
+ {{ var.name }}
+ {{ var.type }} + {% if var.required==true %} / obligatori{% endif %} + {% if var.unique==true %} / únic{% endif %} +
+ {% if var.version %}afegit a la versió {{ var.version }}{% endif %} +
+

+ {{ var.short }}
+ {% if var.allowed != nil %} + {{ var.allowed }} + {% endif %} +

+

+ {{ var.description | markdownify }} +

+ {% if var.name == "type" %} +
+ Valor:
+ {{ page.title | downcase }} +
+ {% elsif var.choices.size > 0 %} +
+ Opcions:
+
    + {% for c in var.choices %} +
  • + {% if c.name == var.default %} + {{ c.name }} (per defecte) + {% else %} + {{ c.name }} + {% endif %} +
  • + {% endfor %} +
+
+ {% elsif var.default != nil %} +
+ Per defecte:
+ {{ var.default }} +
+ {% endif %} +
+ +--- + +## Exemples + +Exemples de camps `enum`, en YAML: + +{%- assign type_choice = formfield_object.items | where: "name", "type" | first %} +{%- if type_choice.choices %} + {%- assign enum_type = type_choice.choices | where: "name", "enum" | first %} + {%- if enum_type.examples %} + {%- for example in enum_type.examples %} + +### {{ example.name }} + +{% if example.description %}{{ example.description | markdownify }}{% elsif example.short %}{{ example.short }}{% else %}La definició del camp, en YAML:{% endif %} + +```yaml +{{ example.code }} +``` + {%- endfor %} + {%- endif %} +{%- endif %} + +{%- endif %} diff --git a/i18n/ca/_build_forms/formfields/expression.md b/i18n/ca/_build_forms/formfields/expression.md new file mode 100644 index 0000000..7d94374 --- /dev/null +++ b/i18n/ca/_build_forms/formfields/expression.md @@ -0,0 +1,131 @@ +--- +layout: default +title: Expression +parent: Camps de formulari +nav_order: 11 +translated_from: 30a3e37e27e9bc9e8472a027b6eb90c3260e8248 +--- + +# Camp Expression +{: .no_toc } + +Un valor calculat amb JavaScript, al navegador o al servidor +{: .fs-6 .fw-300 } + +--- + +## Propietats + +Les propietats disponibles per a un camp `expression`, agrupades per finalitat: + +{% assign help = site.data.help %} +{% assign formsyaml = help | where: "link", "forms" | first %} +{% assign form_object = formsyaml.help | where: "name", "Form" | first %} +{% assign formfield_object = form_object.help | where: "name", "Formfield" | first %} + +{%- if formfield_object and formfield_object.items %} + + + + + + + + + + {% assign groups = formfield_object.items | map: "group" | compact | uniq | sort_natural %} + {% for group in groups %} + {% assign group_properties = formfield_object.items | where: "group", group %} + + + + {% for var in group_properties %} + {%- assign item_types = var.with_types | split: ", " %} + {%- assign type_match = false %} + {%- if var.with_types %} + {%- if item_types contains "expression" %} + {%- assign type_match = true %} + {%- endif %} + {%- else %} + {%- assign type_match = true %} + {%- endif %} + {%- if type_match %} + + + + + {%- endif %} + {% endfor %} + {% endfor %} + +
AtributComentaris
+ {{ group }} +
+ {{ var.name }}
+ {{ var.type }} + {% if var.required==true %} / obligatori{% endif %} + {% if var.unique==true %} / únic{% endif %} +
+ {% if var.version %}afegit a la versió {{ var.version }}{% endif %} +
+

+ {{ var.short }}
+ {% if var.allowed != nil %} + {{ var.allowed }} + {% endif %} +

+

+ {{ var.description | markdownify }} +

+ {% if var.name == "type" %} +
+ Valor:
+ {{ page.title | downcase }} +
+ {% elsif var.choices.size > 0 %} +
+ Opcions:
+
    + {% for c in var.choices %} +
  • + {% if c.name == var.default %} + {{ c.name }} (per defecte) + {% else %} + {{ c.name }} + {% endif %} +
  • + {% endfor %} +
+
+ {% elsif var.default != nil %} +
+ Per defecte:
+ {{ var.default }} +
+ {% endif %} +
+ +--- + +## Exemples + +Exemples de camps `expression`, en YAML: + +{%- assign type_choice = formfield_object.items | where: "name", "type" | first %} +{%- if type_choice.choices %} + {%- assign expression_type = type_choice.choices | where: "name", "expression" | first %} + {%- if expression_type.examples %} + {%- for example in expression_type.examples %} + +### {{ example.name }} + +{% if example.description %}{{ example.description | markdownify }}{% elsif example.short %}{{ example.short }}{% else %}La definició del camp, en YAML:{% endif %} + +```yaml +{{ example.code }} +``` + {%- endfor %} + {%- endif %} +{%- endif %} + +{%- endif %} diff --git a/i18n/ca/_build_forms/formfields/file.md b/i18n/ca/_build_forms/formfields/file.md new file mode 100644 index 0000000..dc19eb8 --- /dev/null +++ b/i18n/ca/_build_forms/formfields/file.md @@ -0,0 +1,131 @@ +--- +layout: default +title: File +parent: Camps de formulari +nav_order: 5 +translated_from: 664227c4b88ae49a9a43d37b5c0f3ce1b50d3b40 +--- + +# Camp File +{: .no_toc } + +Puja fitxers, com ara fitxers de configuració o certificats +{: .fs-6 .fw-300 } + +--- + +## Propietats + +Les propietats disponibles per a un camp `file`, agrupades per finalitat: + +{% assign help = site.data.help %} +{% assign formsyaml = help | where: "link", "forms" | first %} +{% assign form_object = formsyaml.help | where: "name", "Form" | first %} +{% assign formfield_object = form_object.help | where: "name", "Formfield" | first %} + +{%- if formfield_object and formfield_object.items %} + + + + + + + + + + {% assign groups = formfield_object.items | map: "group" | compact | uniq | sort_natural %} + {% for group in groups %} + {% assign group_properties = formfield_object.items | where: "group", group %} + + + + {% for var in group_properties %} + {%- assign item_types = var.with_types | split: ", " %} + {%- assign type_match = false %} + {%- if var.with_types %} + {%- if item_types contains "file" %} + {%- assign type_match = true %} + {%- endif %} + {%- else %} + {%- assign type_match = true %} + {%- endif %} + {%- if type_match %} + + + + + {%- endif %} + {% endfor %} + {% endfor %} + +
AtributComentaris
+ {{ group }} +
+ {{ var.name }}
+ {{ var.type }} + {% if var.required==true %} / obligatori{% endif %} + {% if var.unique==true %} / únic{% endif %} +
+ {% if var.version %}afegit a la versió {{ var.version }}{% endif %} +
+

+ {{ var.short }}
+ {% if var.allowed != nil %} + {{ var.allowed }} + {% endif %} +

+

+ {{ var.description | markdownify }} +

+ {% if var.name == "type" %} +
+ Valor:
+ {{ page.title | downcase }} +
+ {% elsif var.choices.size > 0 %} +
+ Opcions:
+
    + {% for c in var.choices %} +
  • + {% if c.name == var.default %} + {{ c.name }} (per defecte) + {% else %} + {{ c.name }} + {% endif %} +
  • + {% endfor %} +
+
+ {% elsif var.default != nil %} +
+ Per defecte:
+ {{ var.default }} +
+ {% endif %} +
+ +--- + +## Exemples + +Exemples de camps `file`, en YAML: + +{%- assign type_choice = formfield_object.items | where: "name", "type" | first %} +{%- if type_choice.choices %} + {%- assign file_type = type_choice.choices | where: "name", "file" | first %} + {%- if file_type.examples %} + {%- for example in file_type.examples %} + +### {{ example.name }} + +{% if example.description %}{{ example.description | markdownify }}{% elsif example.short %}{{ example.short }}{% else %}La definició del camp, en YAML:{% endif %} + +```yaml +{{ example.code }} +``` + {%- endfor %} + {%- endif %} +{%- endif %} + +{%- endif %} diff --git a/i18n/ca/_build_forms/formfields/html.md b/i18n/ca/_build_forms/formfields/html.md new file mode 100644 index 0000000..62508e4 --- /dev/null +++ b/i18n/ca/_build_forms/formfields/html.md @@ -0,0 +1,131 @@ +--- +layout: default +title: Html +parent: Camps de formulari +nav_order: 4 +translated_from: 473e446a98ddcabefb726ff75033eb3ad7135fc4 +--- + +# Camp Html +{: .no_toc } + +Contingut HTML enriquit dins d'un formulari +{: .fs-6 .fw-300 } + +--- + +## Propietats + +Les propietats disponibles per a un camp `html`, agrupades per finalitat: + +{% assign help = site.data.help %} +{% assign formsyaml = help | where: "link", "forms" | first %} +{% assign form_object = formsyaml.help | where: "name", "Form" | first %} +{% assign formfield_object = form_object.help | where: "name", "Formfield" | first %} + +{%- if formfield_object and formfield_object.items %} + + + + + + + + + + {% assign groups = formfield_object.items | map: "group" | compact | uniq | sort_natural %} + {% for group in groups %} + {% assign group_properties = formfield_object.items | where: "group", group %} + + + + {% for var in group_properties %} + {%- assign item_types = var.with_types | split: ", " %} + {%- assign type_match = false %} + {%- if var.with_types %} + {%- if item_types contains "html" %} + {%- assign type_match = true %} + {%- endif %} + {%- else %} + {%- assign type_match = true %} + {%- endif %} + {%- if type_match %} + + + + + {%- endif %} + {% endfor %} + {% endfor %} + +
AtributComentaris
+ {{ group }} +
+ {{ var.name }}
+ {{ var.type }} + {% if var.required==true %} / obligatori{% endif %} + {% if var.unique==true %} / únic{% endif %} +
+ {% if var.version %}afegit a la versió {{ var.version }}{% endif %} +
+

+ {{ var.short }}
+ {% if var.allowed != nil %} + {{ var.allowed }} + {% endif %} +

+

+ {{ var.description | markdownify }} +

+ {% if var.name == "type" %} +
+ Valor:
+ {{ page.title | downcase }} +
+ {% elsif var.choices.size > 0 %} +
+ Opcions:
+
    + {% for c in var.choices %} +
  • + {% if c.name == var.default %} + {{ c.name }} (per defecte) + {% else %} + {{ c.name }} + {% endif %} +
  • + {% endfor %} +
+
+ {% elsif var.default != nil %} +
+ Per defecte:
+ {{ var.default }} +
+ {% endif %} +
+ +--- + +## Exemples + +Exemples de camps `html`, en YAML: + +{%- assign type_choice = formfield_object.items | where: "name", "type" | first %} +{%- if type_choice.choices %} + {%- assign html_type = type_choice.choices | where: "name", "html" | first %} + {%- if html_type.examples %} + {%- for example in html_type.examples %} + +### {{ example.name }} + +{% if example.description %}{{ example.description | markdownify }}{% elsif example.short %}{{ example.short }}{% else %}La definició del camp, en YAML:{% endif %} + +```yaml +{{ example.code }} +``` + {%- endfor %} + {%- endif %} +{%- endif %} + +{%- endif %} diff --git a/i18n/ca/_build_forms/formfields/index.md b/i18n/ca/_build_forms/formfields/index.md new file mode 100644 index 0000000..10f693b --- /dev/null +++ b/i18n/ca/_build_forms/formfields/index.md @@ -0,0 +1,62 @@ +--- +layout: default +title: Camps de formulari +nav_order: 2 +has_children: true +has_toc: false +permalink: /formfields/ +translated_from: f87478aaaa3db6bc7523c8f49e4aea097b90b003 +--- + +# Camps de formulari +{: .no_toc } + +Els controls d'entrada d'un formulari +{: .fs-6 .fw-300 } + +--- + +Per als autors de formularis: els tipus de camp que pot contenir un formulari i les propietats que admet cadascun. + +Els camps de formulari defineixen els controls d'entrada d'un formulari. Cada tipus de camp té les seves pròpies propietats i el seu propi comportament per recollir un tipus concret de dades. + +Tria el tipus de camp que correspongui a les dades que vols recollir, des de text pla fins a llistes estructurades. + +--- + +## Propietats comunes + +Tots els camps de formulari comparteixen dues propietats fonamentals: + +- **name** (string, obligatori): l'identificador únic del camp +- **type** (string, obligatori): el tipus de camp, que determina quina de les pàgines següents descriu les propietats disponibles + +Cada tipus de camp afegeix propietats pròpies de la seva funció. Selecciona un tipus de camp a la barra lateral de navegació o a la taula següent per obrir la referència completa de les seves propietats: + +{% assign help = site.data.help %} +{% assign formsyaml = help | where: "link", "forms" | first %} +{% assign form_object = formsyaml.help | where: "name", "Form" | first %} +{% assign formfield = form_object.help | where: "name", "Formfield" | first %} +{% assign formfile = formfield.items | where: "name", "type" | first %} + + + + + + + + + +{% for type in formfile.choices %} + + + + + +{% endfor %} + +
Tipus de campDescripció
{{ type.name }}{{ type.description | markdownify }}
diff --git a/i18n/ca/_build_forms/formfields/list.md b/i18n/ca/_build_forms/formfields/list.md new file mode 100644 index 0000000..80a1f68 --- /dev/null +++ b/i18n/ca/_build_forms/formfields/list.md @@ -0,0 +1,396 @@ +--- +layout: default +title: List +parent: Camps de formulari +nav_order: 13 +translated_from: b6209effaf1cc9783a27c36669004a239751fb3e +--- + +# Camp List +{: .no_toc } + +Una taula de files, cadascuna editada en un subformulari +{: .fs-6 .fw-300 } + +--- + +Un camp list mostra una taula de files, cadascuna creada i editada en un panell de **subformulari** dedicat (un patró de navegació en profunditat). Substitueix el camp `table`, que es va eliminar a la 7.0.0. + +--- + +## Característiques principals + +El camp list ofereix les possibilitats següents: + +- Cada fila s'edita en un subformulari a pantalla completa, amb accés a tots els tipus de camp, incloses les llistes niades. +- El subformulari és un formulari en si mateix, de tipus `subform`, i es pot **reutilitzar en diversos camps list** de formularis diferents (p. ex. un sol subformulari `Address` compartit per clients, proveïdors, comandes…). +- Les propietats de marcatge (`insertMarker`, `updateMarker`, `deleteMarker`) permeten patrons de playbook idempotents. +- Amb `allowDelete: false`, les files que ja existien estan protegides; només es poden eliminar les files afegides a la sessió actual (les que porten l'`insertMarker`). +- La propietat `columns` controla quins camps del subformulari apareixen com a columnes a la taula de resum. +- La sortida és sempre una matriu d'objectes. Quan es generen les extravars, es respecten els `model`, `output`, `outputObject` i `valueColumn` declarats als camps del subformulari. + +--- + +## Declaració del subformulari + +Un subformulari és un formulari en si mateix amb `type: subform`, en un fitxer de la carpeta de formularis com qualsevol altre formulari. Accepta la mateixa matriu `fields` que qualsevol altre formulari, però no apareix mai a la llista de mosaics de formularis i no s'envia mai directament. + +```yaml +- name: Address + type: subform + fields: + - name: street + type: text + label: Street + required: true + - name: city + type: text + label: City + required: true + - name: country + type: text + label: Country +``` + +--- + +## Propietats + +Les propietats disponibles per a un camp `list`, agrupades per finalitat: + +{% assign help = site.data.help %} +{% assign formsyaml = help | where: "link", "forms" | first %} +{% assign form_object = formsyaml.help | where: "name", "Form" | first %} +{% assign formfield_object = form_object.help | where: "name", "Formfield" | first %} + +{%- if formfield_object and formfield_object.items %} + + + + + + + + + + {% assign groups = formfield_object.items | map: "group" | compact | uniq | sort_natural %} + {% for group in groups %} + {% assign group_properties = formfield_object.items | where: "group", group %} + {% assign has_list_props = false %} + {% for var in group_properties %} + {%- assign item_types = var.with_types | split: ", " %} + {%- if var.with_types == nil or item_types contains "list" %} + {%- assign has_list_props = true %} + {%- endif %} + {% endfor %} + {% if has_list_props %} + + + + {% for var in group_properties %} + {%- assign item_types = var.with_types | split: ", " %} + {%- assign type_match = false %} + {%- if var.with_types %} + {%- if item_types contains "list" %} + {%- assign type_match = true %} + {%- endif %} + {%- else %} + {%- assign type_match = true %} + {%- endif %} + {%- if type_match %} + + + + + {%- endif %} + {% endfor %} + {% endif %} + {% endfor %} + +
AtributComentaris
+ {{ group }} +
+ {{ var.name }}
+ {{ var.type }} + {% if var.required==true %} / obligatori{% endif %} + {% if var.unique==true %} / únic{% endif %} +
+ {% if var.version %}afegit a la versió {{ var.version }}{% endif %} +
+

+ {{ var.short }}
+ {% if var.allowed != nil %} + {{ var.allowed }} + {% endif %} +

+

+ {{ var.description | markdownify }} +

+ {% if var.name == "type" %} +
+ Valor:
+ list +
+ {% elsif var.choices.size > 0 %} +
+ Opcions:
+
    + {% for c in var.choices %} +
  • + {% if c.name == var.default %} + {{ c.name }} (per defecte) + {% else %} + {{ c.name }} + {% endif %} +
  • + {% endfor %} +
+
+ {% elsif var.default != nil %} +
+ Per defecte:
+ {{ var.default }} +
+ {% endif %} + {% if var.examples.size > 0 %} +
+ Exemples + {% for ex in var.examples %} +

{{ ex.name }}

+
{{ ex.code }}
+ {% endfor %} +
+ {% endif %} +
+ +{%- endif %} + +--- + +## Exemples + +### Subformulari d'adreça compartit + +Un subformulari `Address` reutilitzat per dos camps list del mateix formulari: + +```yaml +- name: Address + type: subform + fields: + - name: street + type: text + label: Street + required: true + - name: city + type: text + label: City + required: true + - name: country + type: text + label: Country + +- name: Create customer + type: ansible + playbook: customer.yaml + roles: [default] + fields: + - name: name + type: text + label: Customer name + required: true + - name: addresses + type: list + label: Addresses + subform: Address + columns: + - city + - country + titleAdd: Add address + titleEdit: Edit address + allowInsert: true + allowDelete: true +``` + +### Seguiment amb marcadors (pensat per a la idempotència) + +Les files precarregades estan protegides, i els marcadors indiquen al playbook quines files són noves, quines han canviat i quines s'han eliminat: + +```yaml +- name: people + type: list + label: People + subform: Person + allowDelete: false # preloaded rows are protected + insertMarker: added # session-added rows remain removable + updateMarker: updated + deleteMarker: removed + columns: + - name + - email +``` + +### Emplenar les files per endavant + +Una llista es pot emplenar per endavant des de tres fonts. En tots els casos, les files resultants han de ser objectes les claus dels quals coincideixin amb els noms dels camps del subformulari referenciat. + +#### `default` estàtic + +Files escrites al mateix formulari: + +```yaml +- name: addresses + type: list + label: Addresses + subform: Address + columns: + - city + - country + default: + - street: Main 1 + city: Brussels + country: BE + - street: Side 22 + city: Paris + country: FR +``` + +#### Des d'una API REST (`expression`) + +Files carregades des d'una API REST per una expressió del costat del servidor: + +```yaml +- name: users + type: list + label: Users + subform: User + columns: + - username + - email + expression: fn.fnRestBasic('get','https://api.example.com/users','','my_api_cred','') +``` + +#### Des d'una consulta a base de dades (`dbConfig` + `query`) + +Files carregades des d'una consulta a base de dades: + +```yaml +- name: servers + type: list + label: Servers + subform: Server + columns: + - hostname + - role + dbConfig: CMDB_CONN + query: SELECT hostname, role FROM servers WHERE active = 1 +``` + +#### Des d'una expressió local (`runLocal`) + +Files calculades al navegador per una expressió local: + +```yaml +- name: ports + type: list + label: Open ports + subform: Port + columns: + - port + - protocol + runLocal: true + expression: | + [ + { port: 22, protocol: 'tcp' }, + { port: 80, protocol: 'tcp' }, + { port: 443, protocol: 'tcp' } + ] +``` + +### Llistes niades + +Un subformulari pot contenir un camp list propi, per tenir una llista dins de cada fila: + +```yaml +- name: Address + type: subform + fields: + - name: street + type: text + label: Street + - name: city + type: text + label: City + +- name: Person + type: subform + fields: + - name: name + type: text + label: Name + required: true + - name: addresses + type: list + label: Addresses + subform: Address + columns: + - street + - city + +- name: My Form + type: ansible + playbook: people.yaml + roles: [default] + fields: + - name: people + type: list + label: People + subform: Person + columns: + - name + - addresses +``` + +### Accedir a les dades del formulari pare amb `__parent__` + +Quan s'obre l'editor de files d'un subformulari, AnsibleForms injecta una variable `__parent__` al subformulari. Conté una instantània de **tots els valors dels camps del formulari pare**, incloses les constants i les variables. + +Fes-hi referència amb la sintaxi d'expressió estàndard `$(...)` a les definicions dels camps del subformulari: + +```yaml +- name: NodeConfig + type: subform + fields: + - name: node_name + type: text + label: Node name + required: true + + - name: node_type + type: enum + # only offer gpu in production environments (parent field) + expression: | + '$(__parent__.environment)' === 'production' + ? ['standard', 'high-memory', 'gpu'] + : ['standard', 'high-memory'] + runLocal: true + default: __auto__ + +- name: Deploy cluster + type: ansible + playbook: deploy.yml + roles: [default] + fields: + - name: environment + type: enum + values: [dev, staging, production] + required: true + + - name: nodes + type: list + subform: NodeConfig + columns: [node_name, node_type] +``` + +{: .note } +> `__parent__` és una eina auxiliar **només del frontend**. Es treu de les extravars d'Ansible i no s'envia mai al playbook. + diff --git a/i18n/ca/_build_forms/formfields/number.md b/i18n/ca/_build_forms/formfields/number.md new file mode 100644 index 0000000..50bc9a0 --- /dev/null +++ b/i18n/ca/_build_forms/formfields/number.md @@ -0,0 +1,131 @@ +--- +layout: default +title: Number +parent: Camps de formulari +nav_order: 6 +translated_from: d9e124b198b3304f9f9894919421d7f938676e75 +--- + +# Camp Number +{: .no_toc } + +Un valor enter o decimal, com ara un port o una quantitat +{: .fs-6 .fw-300 } + +--- + +## Propietats + +Les propietats disponibles per a un camp `number`, agrupades per finalitat: + +{% assign help = site.data.help %} +{% assign formsyaml = help | where: "link", "forms" | first %} +{% assign form_object = formsyaml.help | where: "name", "Form" | first %} +{% assign formfield_object = form_object.help | where: "name", "Formfield" | first %} + +{%- if formfield_object and formfield_object.items %} + + + + + + + + + + {% assign groups = formfield_object.items | map: "group" | compact | uniq | sort_natural %} + {% for group in groups %} + {% assign group_properties = formfield_object.items | where: "group", group %} + + + + {% for var in group_properties %} + {%- assign item_types = var.with_types | split: ", " %} + {%- assign type_match = false %} + {%- if var.with_types %} + {%- if item_types contains "number" %} + {%- assign type_match = true %} + {%- endif %} + {%- else %} + {%- assign type_match = true %} + {%- endif %} + {%- if type_match %} + + + + + {%- endif %} + {% endfor %} + {% endfor %} + +
AtributComentaris
+ {{ group }} +
+ {{ var.name }}
+ {{ var.type }} + {% if var.required==true %} / obligatori{% endif %} + {% if var.unique==true %} / únic{% endif %} +
+ {% if var.version %}afegit a la versió {{ var.version }}{% endif %} +
+

+ {{ var.short }}
+ {% if var.allowed != nil %} + {{ var.allowed }} + {% endif %} +

+

+ {{ var.description | markdownify }} +

+ {% if var.name == "type" %} +
+ Valor:
+ {{ page.title | downcase }} +
+ {% elsif var.choices.size > 0 %} +
+ Opcions:
+
    + {% for c in var.choices %} +
  • + {% if c.name == var.default %} + {{ c.name }} (per defecte) + {% else %} + {{ c.name }} + {% endif %} +
  • + {% endfor %} +
+
+ {% elsif var.default != nil %} +
+ Per defecte:
+ {{ var.default }} +
+ {% endif %} +
+ +--- + +## Exemples + +Exemples de camps `number`, en YAML: + +{%- assign type_choice = formfield_object.items | where: "name", "type" | first %} +{%- if type_choice.choices %} + {%- assign number_type = type_choice.choices | where: "name", "number" | first %} + {%- if number_type.examples %} + {%- for example in number_type.examples %} + +### {{ example.name }} + +{% if example.description %}{{ example.description | markdownify }}{% elsif example.short %}{{ example.short }}{% else %}La definició del camp, en YAML:{% endif %} + +```yaml +{{ example.code }} +``` + {%- endfor %} + {%- endif %} +{%- endif %} + +{%- endif %} diff --git a/i18n/ca/_build_forms/formfields/password.md b/i18n/ca/_build_forms/formfields/password.md new file mode 100644 index 0000000..12b9f79 --- /dev/null +++ b/i18n/ca/_build_forms/formfields/password.md @@ -0,0 +1,131 @@ +--- +layout: default +title: Password +parent: Camps de formulari +nav_order: 7 +translated_from: 2fa25c0e69e736fb4edc9a31a8c88e3020294fa6 +--- + +# Camp Password +{: .no_toc } + +Un valor emmascarat, per a contrasenyes, secrets i tokens +{: .fs-6 .fw-300 } + +--- + +## Propietats + +Les propietats disponibles per a un camp `password`, agrupades per finalitat: + +{% assign help = site.data.help %} +{% assign formsyaml = help | where: "link", "forms" | first %} +{% assign form_object = formsyaml.help | where: "name", "Form" | first %} +{% assign formfield_object = form_object.help | where: "name", "Formfield" | first %} + +{%- if formfield_object and formfield_object.items %} + + + + + + + + + + {% assign groups = formfield_object.items | map: "group" | compact | uniq | sort_natural %} + {% for group in groups %} + {% assign group_properties = formfield_object.items | where: "group", group %} + + + + {% for var in group_properties %} + {%- assign item_types = var.with_types | split: ", " %} + {%- assign type_match = false %} + {%- if var.with_types %} + {%- if item_types contains "password" %} + {%- assign type_match = true %} + {%- endif %} + {%- else %} + {%- assign type_match = true %} + {%- endif %} + {%- if type_match %} + + + + + {%- endif %} + {% endfor %} + {% endfor %} + +
AtributComentaris
+ {{ group }} +
+ {{ var.name }}
+ {{ var.type }} + {% if var.required==true %} / obligatori{% endif %} + {% if var.unique==true %} / únic{% endif %} +
+ {% if var.version %}afegit a la versió {{ var.version }}{% endif %} +
+

+ {{ var.short }}
+ {% if var.allowed != nil %} + {{ var.allowed }} + {% endif %} +

+

+ {{ var.description | markdownify }} +

+ {% if var.name == "type" %} +
+ Valor:
+ {{ page.title | downcase }} +
+ {% elsif var.choices.size > 0 %} +
+ Opcions:
+
    + {% for c in var.choices %} +
  • + {% if c.name == var.default %} + {{ c.name }} (per defecte) + {% else %} + {{ c.name }} + {% endif %} +
  • + {% endfor %} +
+
+ {% elsif var.default != nil %} +
+ Per defecte:
+ {{ var.default }} +
+ {% endif %} +
+ +--- + +## Exemples + +Exemples de camps `password`, en YAML: + +{%- assign type_choice = formfield_object.items | where: "name", "type" | first %} +{%- if type_choice.choices %} + {%- assign password_type = type_choice.choices | where: "name", "password" | first %} + {%- if password_type.examples %} + {%- for example in password_type.examples %} + +### {{ example.name }} + +{% if example.description %}{{ example.description | markdownify }}{% elsif example.short %}{{ example.short }}{% else %}La definició del camp, en YAML:{% endif %} + +```yaml +{{ example.code }} +``` + {%- endfor %} + {%- endif %} +{%- endif %} + +{%- endif %} diff --git a/i18n/ca/_build_forms/formfields/radio.md b/i18n/ca/_build_forms/formfields/radio.md new file mode 100644 index 0000000..c0ad048 --- /dev/null +++ b/i18n/ca/_build_forms/formfields/radio.md @@ -0,0 +1,131 @@ +--- +layout: default +title: Radio +parent: Camps de formulari +nav_order: 9 +translated_from: b1deb8f285c46f2be77ed0f920710248c998d6f2 +--- + +# Camp Radio +{: .no_toc } + +Una opció d'entre un conjunt d'opcions mútuament excloents +{: .fs-6 .fw-300 } + +--- + +## Propietats + +Les propietats disponibles per a un camp `radio`, agrupades per finalitat: + +{% assign help = site.data.help %} +{% assign formsyaml = help | where: "link", "forms" | first %} +{% assign form_object = formsyaml.help | where: "name", "Form" | first %} +{% assign formfield_object = form_object.help | where: "name", "Formfield" | first %} + +{%- if formfield_object and formfield_object.items %} + + + + + + + + + + {% assign groups = formfield_object.items | map: "group" | compact | uniq | sort_natural %} + {% for group in groups %} + {% assign group_properties = formfield_object.items | where: "group", group %} + + + + {% for var in group_properties %} + {%- assign item_types = var.with_types | split: ", " %} + {%- assign type_match = false %} + {%- if var.with_types %} + {%- if item_types contains "radio" %} + {%- assign type_match = true %} + {%- endif %} + {%- else %} + {%- assign type_match = true %} + {%- endif %} + {%- if type_match %} + + + + + {%- endif %} + {% endfor %} + {% endfor %} + +
AtributComentaris
+ {{ group }} +
+ {{ var.name }}
+ {{ var.type }} + {% if var.required==true %} / obligatori{% endif %} + {% if var.unique==true %} / únic{% endif %} +
+ {% if var.version %}afegit a la versió {{ var.version }}{% endif %} +
+

+ {{ var.short }}
+ {% if var.allowed != nil %} + {{ var.allowed }} + {% endif %} +

+

+ {{ var.description | markdownify }} +

+ {% if var.name == "type" %} +
+ Valor:
+ {{ page.title | downcase }} +
+ {% elsif var.choices.size > 0 %} +
+ Opcions:
+
    + {% for c in var.choices %} +
  • + {% if c.name == var.default %} + {{ c.name }} (per defecte) + {% else %} + {{ c.name }} + {% endif %} +
  • + {% endfor %} +
+
+ {% elsif var.default != nil %} +
+ Per defecte:
+ {{ var.default }} +
+ {% endif %} +
+ +--- + +## Exemples + +Exemples de camps `radio`, en YAML: + +{%- assign type_choice = formfield_object.items | where: "name", "type" | first %} +{%- if type_choice.choices %} + {%- assign radio_type = type_choice.choices | where: "name", "radio" | first %} + {%- if radio_type.examples %} + {%- for example in radio_type.examples %} + +### {{ example.name }} + +{% if example.description %}{{ example.description | markdownify }}{% elsif example.short %}{{ example.short }}{% else %}La definició del camp, en YAML:{% endif %} + +```yaml +{{ example.code }} +``` + {%- endfor %} + {%- endif %} +{%- endif %} + +{%- endif %} diff --git a/i18n/ca/_build_forms/formfields/text.md b/i18n/ca/_build_forms/formfields/text.md new file mode 100644 index 0000000..0a106f2 --- /dev/null +++ b/i18n/ca/_build_forms/formfields/text.md @@ -0,0 +1,131 @@ +--- +layout: default +title: Text +parent: Camps de formulari +nav_order: 1 +translated_from: fa7de095c8a640826ee0825522ce2249ace822f0 +--- + +# Camp Text +{: .no_toc } + +Una sola línia de text, com ara un nom o un nom d'amfitrió +{: .fs-6 .fw-300 } + +--- + +## Propietats + +Les propietats disponibles per a un camp `text`, agrupades per finalitat: + +{% assign help = site.data.help %} +{% assign formsyaml = help | where: "link", "forms" | first %} +{% assign form_object = formsyaml.help | where: "name", "Form" | first %} +{% assign formfield_object = form_object.help | where: "name", "Formfield" | first %} + +{%- if formfield_object and formfield_object.items %} + + + + + + + + + + {% assign groups = formfield_object.items | map: "group" | compact | uniq | sort_natural %} + {% for group in groups %} + {% assign group_properties = formfield_object.items | where: "group", group %} + + + + {% for var in group_properties %} + {%- assign item_types = var.with_types | split: ", " %} + {%- assign type_match = false %} + {%- if var.with_types %} + {%- if item_types contains "text" %} + {%- assign type_match = true %} + {%- endif %} + {%- else %} + {%- assign type_match = true %} + {%- endif %} + {%- if type_match %} + + + + + {%- endif %} + {% endfor %} + {% endfor %} + +
AtributComentaris
+ {{ group }} +
+ {{ var.name }}
+ {{ var.type }} + {% if var.required==true %} / obligatori{% endif %} + {% if var.unique==true %} / únic{% endif %} +
+ {% if var.version %}afegit a la versió {{ var.version }}{% endif %} +
+

+ {{ var.short }}
+ {% if var.allowed != nil %} + {{ var.allowed }} + {% endif %} +

+

+ {{ var.description | markdownify }} +

+ {% if var.name == "type" %} +
+ Valor:
+ {{ page.title | downcase }} +
+ {% elsif var.choices.size > 0 %} +
+ Opcions:
+
    + {% for c in var.choices %} +
  • + {% if c.name == var.default %} + {{ c.name }} (per defecte) + {% else %} + {{ c.name }} + {% endif %} +
  • + {% endfor %} +
+
+ {% elsif var.default != nil %} +
+ Per defecte:
+ {{ var.default }} +
+ {% endif %} +
+ +--- + +## Exemples + +Exemples de camps `text`, en YAML: + +{%- assign type_choice = formfield_object.items | where: "name", "type" | first %} +{%- if type_choice.choices %} + {%- assign text_type = type_choice.choices | where: "name", "text" | first %} + {%- if text_type.examples %} + {%- for example in text_type.examples %} + +### {{ example.name }} + +{% if example.description %}{{ example.description | markdownify }}{% elsif example.short %}{{ example.short }}{% else %}La definició del camp, en YAML:{% endif %} + +```yaml +{{ example.code }} +``` + {%- endfor %} + {%- endif %} +{%- endif %} + +{%- endif %} diff --git a/i18n/ca/_build_forms/formfields/textarea.md b/i18n/ca/_build_forms/formfields/textarea.md new file mode 100644 index 0000000..dacaaad --- /dev/null +++ b/i18n/ca/_build_forms/formfields/textarea.md @@ -0,0 +1,131 @@ +--- +layout: default +title: Textarea +parent: Camps de formulari +nav_order: 2 +translated_from: 9ce412065c2c12d9f6b76219033303d20447167e +--- + +# Camp Textarea +{: .no_toc } + +Text de diverses línies, com ara una descripció o un fragment de configuració +{: .fs-6 .fw-300 } + +--- + +## Propietats + +Les propietats disponibles per a un camp `textarea`, agrupades per finalitat: + +{% assign help = site.data.help %} +{% assign formsyaml = help | where: "link", "forms" | first %} +{% assign form_object = formsyaml.help | where: "name", "Form" | first %} +{% assign formfield_object = form_object.help | where: "name", "Formfield" | first %} + +{%- if formfield_object and formfield_object.items %} + + + + + + + + + + {% assign groups = formfield_object.items | map: "group" | compact | uniq | sort_natural %} + {% for group in groups %} + {% assign group_properties = formfield_object.items | where: "group", group %} + + + + {% for var in group_properties %} + {%- assign item_types = var.with_types | split: ", " %} + {%- assign type_match = false %} + {%- if var.with_types %} + {%- if item_types contains "textarea" %} + {%- assign type_match = true %} + {%- endif %} + {%- else %} + {%- assign type_match = true %} + {%- endif %} + {%- if type_match %} + + + + + {%- endif %} + {% endfor %} + {% endfor %} + +
AtributComentaris
+ {{ group }} +
+ {{ var.name }}
+ {{ var.type }} + {% if var.required==true %} / obligatori{% endif %} + {% if var.unique==true %} / únic{% endif %} +
+ {% if var.version %}afegit a la versió {{ var.version }}{% endif %} +
+

+ {{ var.short }}
+ {% if var.allowed != nil %} + {{ var.allowed }} + {% endif %} +

+

+ {{ var.description | markdownify }} +

+ {% if var.name == "type" %} +
+ Valor:
+ {{ page.title | downcase }} +
+ {% elsif var.choices.size > 0 %} +
+ Opcions:
+
    + {% for c in var.choices %} +
  • + {% if c.name == var.default %} + {{ c.name }} (per defecte) + {% else %} + {{ c.name }} + {% endif %} +
  • + {% endfor %} +
+
+ {% elsif var.default != nil %} +
+ Per defecte:
+ {{ var.default }} +
+ {% endif %} +
+ +--- + +## Exemples + +Exemples de camps `textarea`, en YAML: + +{%- assign type_choice = formfield_object.items | where: "name", "type" | first %} +{%- if type_choice.choices %} + {%- assign textarea_type = type_choice.choices | where: "name", "textarea" | first %} + {%- if textarea_type.examples %} + {%- for example in textarea_type.examples %} + +### {{ example.name }} + +{% if example.description %}{{ example.description | markdownify }}{% elsif example.short %}{{ example.short }}{% else %}La definició del camp, en YAML:{% endif %} + +```yaml +{{ example.code }} +``` + {%- endfor %} + {%- endif %} +{%- endif %} + +{%- endif %} diff --git a/i18n/ca/_build_forms/formfields/yaml.md b/i18n/ca/_build_forms/formfields/yaml.md new file mode 100644 index 0000000..17ba3c7 --- /dev/null +++ b/i18n/ca/_build_forms/formfields/yaml.md @@ -0,0 +1,188 @@ +--- +layout: default +title: YAML +parent: Camps de formulari +nav_order: 14 +translated_from: c7439c165a54cf525a91d0458a268a66ee8a136f +--- + +# Camp YAML +{: .no_toc } + +Dades estructurades en un editor YAML, amb validació i importació de fitxers +{: .fs-6 .fw-300 } + +--- + +## Propietats + +Les propietats disponibles per a un camp `yaml`, agrupades per finalitat: + +{% assign help = site.data.help %} +{% assign formsyaml = help | where: "link", "forms" | first %} +{% assign form_object = formsyaml.help | where: "name", "Form" | first %} +{% assign formfield_object = form_object.help | where: "name", "Formfield" | first %} + +{%- if formfield_object and formfield_object.items %} + + + + + + + + + + {% assign groups = formfield_object.items | map: "group" | compact | uniq | sort_natural %} + {% for group in groups %} + {% assign group_properties = formfield_object.items | where: "group", group %} + + + + {% for var in group_properties %} + {%- assign item_types = var.with_types | split: ", " %} + {%- assign type_match = false %} + {%- if var.with_types %} + {%- if item_types contains "yaml" %} + {%- assign type_match = true %} + {%- endif %} + {%- else %} + {%- assign type_match = true %} + {%- endif %} + {%- if type_match %} + + + + + {%- endif %} + {% endfor %} + {% endfor %} + +
AtributComentaris
+ {{ group }} +
+ {{ var.name }}
+ {{ var.type }} + {% if var.required==true %} / obligatori{% endif %} + {% if var.unique==true %} / únic{% endif %} +
+ {% if var.version %}afegit a la versió {{ var.version }}{% endif %} +
+

+ {{ var.short }}
+ {% if var.allowed != nil %} + {{ var.allowed }} + {% endif %} +

+

+ {{ var.description | markdownify }} +

+ {% if var.name == "type" %} +
+ Valor:
+ {{ page.title | downcase }} +
+ {% elsif var.choices.size > 0 %} +
+ Opcions:
+
    + {% for c in var.choices %} +
  • + {% if c.name == var.default %} + {{ c.name }} (per defecte) + {% else %} + {{ c.name }} + {% endif %} +
  • + {% endfor %} +
+
+ {% elsif var.default != nil %} +
+ Per defecte:
+ {{ var.default }} +
+ {% endif %} +
+ +--- + +## Exemples + +Exemples de camps `yaml`, en YAML: + +{%- assign type_choice = formfield_object.items | where: "name", "type" | first %} +{%- if type_choice.choices %} + {%- assign yaml_type = type_choice.choices | where: "name", "yaml" | first %} + {%- if yaml_type.examples %} + {%- for example in yaml_type.examples %} + +### {{ example.name }} + +{% if example.description %}{{ example.description | markdownify }}{% elsif example.short %}{{ example.short }}{% else %}La definició del camp, en YAML:{% endif %} + +```yaml +{{ example.code }} +``` + {%- endfor %} + {%- endif %} +{%- endif %} + +{%- endif %} + +--- + +## Accedir a les dades del formulari pare amb `__parent__` + +Quan un camp `yaml` fa servir el mode `subform`, AnsibleForms injecta una variable `__parent__` al subformulari. Conté una instantània de **tots els valors dels camps del formulari pare** en el moment en què s'obre l'editor, incloses les constants i les variables. + +Fes-hi referència amb la sintaxi d'expressió estàndard `$(...)` a les definicions dels camps del subformulari: + +```yaml +- name: NetworkConfig + type: subform + fields: + - name: interface + type: text + label: Interface + required: true + + - name: vlan + type: enum + label: VLAN + # filter available VLANs based on the parent's selected region + query: "select id,name from vlans where region='$(__parent__.region)'" + dbConfig: + name: MYDB + type: mysql + valueColumn: id + placeholderColumn: name + + - name: mtu + type: number + label: MTU + # default to 9000 in production, 1500 elsewhere + default: "'$(__parent__.environment)' === 'production' ? 9000 : 1500" + evalDefault: true + +- name: Configure server + type: ansible + playbook: configure.yml + roles: [default] + fields: + - name: environment + type: enum + values: [dev, staging, production] + + - name: region + type: enum + values: [eu-west-1, us-east-1, ap-southeast-1] + + - name: nic + type: yaml + label: Network interface + subform: NetworkConfig +``` + +{: .note } +> `__parent__` és una eina auxiliar **només del frontend**. Es treu de les extravars d'Ansible i no s'envia mai al playbook. diff --git a/i18n/ca/_build_forms/forms/ansible.md b/i18n/ca/_build_forms/forms/ansible.md new file mode 100644 index 0000000..88064b3 --- /dev/null +++ b/i18n/ca/_build_forms/forms/ansible.md @@ -0,0 +1,110 @@ +--- +layout: default +title: Formularis d'Ansible +parent: Formularis +nav_order: 2 +translated_from: 804c2e6a40f7cec1287a7aa1df63085190c4ac36 +--- + +# Formularis d'Ansible +{: .no_toc } + +Formularis que executen un playbook d'Ansible local +{: .fs-6 .fw-300 } + +--- + +{% assign help = site.data.help %} +{% assign formsyaml = help | where: "link", "forms" | first %} +{% assign form_object = formsyaml.help | where: "name", "Form" | first %} +{% assign type_prop = form_object.items | where: "name", "type" | first %} +{% assign ansible_choice = type_prop.choices | where: "name", "ansible" | first %} + +{{ ansible_choice.description | markdownify }} + +{% if ansible_choice.examples.size > 0 %} +{% for e in ansible_choice.examples %} +**{{ e.name }}** +{% highlight yaml %} +{{ e.code }} +{% endhighlight %} +{% endfor %} +{% endif %} + +--- + +## Propietats + +Propietats específiques de `type: ansible`, a més de les [propietats comunes dels formularis](common.html). + +{% assign ansible_props = form_object.items | where_exp: "p", "p.with_types contains 'ansible'" %} +{% assign ansible_groups = ansible_props | map: "group" | uniq | sort_natural %} +{% for group in ansible_groups %} +{% assign group_props = ansible_props | where: "group", group %} + +--- + +## {{ group | capitalize }} + + + + + + + + + + {% for var in group_props %} + + + + + {% endfor %} + +
AtributComentaris
+ {{ var.name }}
+ {{ var.type }} + {% if var.required == true %} / obligatori{% endif %} +
+ {% if var.version %}afegit a la versió {{ var.version }}{% endif %} +
+

+ {{ var.short }}
+ {% if var.allowed != nil %} + {{ var.allowed }} + {% endif %} +

+

{{ var.description | markdownify }}

+ {% if var.choices.size > 0 %} +
+ Opcions:
+
    + {% for c in var.choices %} +
  • + {% if c.name == var.default %} + {{ c.name }} (per defecte) + {% else %} + {{ c.name }} + {% endif %} +
  • + {% endfor %} +
+
+ {% elsif var.default != nil %} +
+ Per defecte: {{ var.default }} +
+ {% endif %} + {% if var.examples %} +

Exemples:

+ {% for e in var.examples %} +
+

{{ forloop.index }}) {{ e.name }}

+{% highlight yaml %} +{{ e.code }} +{% endhighlight %} +
+ {% endfor %} + {% endif %} +
+{% endfor %} diff --git a/i18n/ca/_build_forms/forms/approval.md b/i18n/ca/_build_forms/forms/approval.md new file mode 100644 index 0000000..544b400 --- /dev/null +++ b/i18n/ca/_build_forms/forms/approval.md @@ -0,0 +1,101 @@ +--- +layout: default +title: Punts d'aprovació +parent: Formularis +nav_order: 8 +translated_from: c2784dd4ac7ac41ef7f18fafdc4a6c468575c405 +--- + +# Punts d'aprovació +{: .no_toc } + +Atura una tasca fins que algú l'aprovi +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +## Com funciona + +Un punt d'aprovació atura la tasca en el lloc que ocupa al formulari fins que un aprovador hi respon: + +{% assign help = site.data.help %} +{% assign formsyaml = help | where: "link", "forms" | first %} +{% assign form_object = formsyaml.help | where: "name", "Form" | first %} +{% assign approval_object = form_object.help | where: "name", "Approval point" | first %} + +{{ approval_object.description | markdownify }} + +--- + +## Aprovar la teva pròpia tasca + +A partir de la 7.3.0, l'usuari que ha llançat una tasca no la pot aprovar, encara que tingui un dels rols de l'aprovació, de manera que cal una segona persona; un administrador sempre pot aprovar, també les seves pròpies tasques. +Qui l'ha llançada encara pot rebutjar (retirar) la seva pròpia tasca. Posa `allowSelf: true` quan també la pugui aprovar, per exemple en un formulari de proves: + +```yaml +approval: + title: Approve the change + message: Please approve this change + roles: + - approvers + allowSelf: true +``` + +--- + +## Atributs + +Els atributs d'un punt d'aprovació: + + + + + + + + + + {% for var in approval_object.items %} + + + + + {% endfor %} + +
AtributComentaris
+ {{ var.name }}
+ {{ var.type}} + {% if var.required==true %} / obligatori{% endif %} + {% if var.unique==true %} / únic{% endif %} +
+ {% if var.version %}afegit a la versió {{var.version}}{% endif %} +
+

+ {{var.short}}
+ {% if var.allowed != nil %} + {{ var.allowed }} + {% endif %} +

+

+ {{ var.description | markdownify }} +

+
+ +--- + +## Exemples + +Exemples de punts d'aprovació, en YAML: + +{% for example in approval_object.examples %} +### {{ forloop.index }}) {{ example.name }} + +{% if example.description %}{{ example.description | markdownify }}{% elsif example.short %}{{ example.short }}{% else %}La definició, en YAML:{% endif %} + +```yaml +{{ example.code }} +``` +{% endfor %} diff --git a/i18n/ca/_build_forms/forms/awx.md b/i18n/ca/_build_forms/forms/awx.md new file mode 100644 index 0000000..02667ee --- /dev/null +++ b/i18n/ca/_build_forms/forms/awx.md @@ -0,0 +1,110 @@ +--- +layout: default +title: Formularis d'AWX +parent: Formularis +nav_order: 3 +translated_from: f5e3e7166f35525eb66bcbd7e085776f44d37c33 +--- + +# Formularis d'AWX +{: .no_toc } + +Formularis que llancen una plantilla de job d'AWX, AAP o Ascender +{: .fs-6 .fw-300 } + +--- + +{% assign help = site.data.help %} +{% assign formsyaml = help | where: "link", "forms" | first %} +{% assign form_object = formsyaml.help | where: "name", "Form" | first %} +{% assign type_prop = form_object.items | where: "name", "type" | first %} +{% assign awx_choice = type_prop.choices | where: "name", "awx" | first %} + +{{ awx_choice.description | markdownify }} + +{% if awx_choice.examples.size > 0 %} +{% for e in awx_choice.examples %} +**{{ e.name }}** +{% highlight yaml %} +{{ e.code }} +{% endhighlight %} +{% endfor %} +{% endif %} + +--- + +## Propietats + +Propietats específiques de `type: awx`, a més de les [propietats comunes dels formularis](common.html). + +{% assign awx_props = form_object.items | where_exp: "p", "p.with_types contains 'awx'" %} +{% assign awx_groups = awx_props | map: "group" | uniq | sort_natural %} +{% for group in awx_groups %} +{% assign group_props = awx_props | where: "group", group %} + +--- + +## {{ group | capitalize }} + + + + + + + + + + {% for var in group_props %} + + + + + {% endfor %} + +
AtributComentaris
+ {{ var.name }}
+ {{ var.type }} + {% if var.required == true %} / obligatori{% endif %} +
+ {% if var.version %}afegit a la versió {{ var.version }}{% endif %} +
+

+ {{ var.short }}
+ {% if var.allowed != nil %} + {{ var.allowed }} + {% endif %} +

+

{{ var.description | markdownify }}

+ {% if var.choices.size > 0 %} +
+ Opcions:
+
    + {% for c in var.choices %} +
  • + {% if c.name == var.default %} + {{ c.name }} (per defecte) + {% else %} + {{ c.name }} + {% endif %} +
  • + {% endfor %} +
+
+ {% elsif var.default != nil %} +
+ Per defecte: {{ var.default }} +
+ {% endif %} + {% if var.examples %} +

Exemples:

+ {% for e in var.examples %} +
+

{{ forloop.index }}) {{ e.name }}

+{% highlight yaml %} +{{ e.code }} +{% endhighlight %} +
+ {% endfor %} + {% endif %} +
+{% endfor %} diff --git a/i18n/ca/_build_forms/forms/common.md b/i18n/ca/_build_forms/forms/common.md new file mode 100644 index 0000000..2d51379 --- /dev/null +++ b/i18n/ca/_build_forms/forms/common.md @@ -0,0 +1,104 @@ +--- +layout: default +title: Propietats comunes +parent: Formularis +nav_order: 1 +translated_from: ce05875209a1cab9ae70d0168723f3aa615e6635 +--- + +# Propietats comunes dels formularis +{: .no_toc } + +Propietats que comparteixen tots els tipus de formulari +{: .fs-6 .fw-300 } + +--- + +Aquestes propietats s'apliquen a **tots els tipus de formulari**: `ansible`, `awx`, `aap`, `ascender`, `semaphore`, `rundeck`, `jenkins`, +`workflow`, `multistep` (obsolet) i `subform`. + +Totes les altres propietats són específiques de cada tipus i es documenten a la pàgina del tipus de formulari corresponent. + +{% assign help = site.data.help %} +{% assign formsyaml = help | where: "link", "forms" | first %} +{% assign form_object = formsyaml.help | where: "name", "Form" | first %} +{% assign common_props = form_object.items | where_exp: "p", "p.with_types == nil" %} + +{{ form_object.description | markdownify }} + +--- + +## Propietats + +Les propietats que comparteixen tots els tipus de formulari: + + + + + + + + + + {% for var in common_props %} + + + + + {% endfor %} + +
AtributComentaris
+ {{ var.name }}
+ {{ var.type }} + {% if var.required == true %} / obligatori{% endif %} + {% if var.unique == true %} / únic{% endif %} +
+ {% if var.version %}afegit a la versió {{ var.version }}{% endif %} +
+

+ {{ var.short }}
+ {% if var.docsObjectLink %} + {% assign link_start = var.docsObjectLink | slice: 0 %} + 🔗 + {% endif %} + {% if var.allowed != nil %} + {{ var.allowed }} + {% endif %} + {% if var.docsObjectLink %} + + {% endif %} +

+

{{ var.description | markdownify }}

+ {% if var.choices.size > 0 %} +
+ Opcions:
+
    + {% for c in var.choices %} +
  • + {% if c.name == var.default %} + {{ c.name }} (per defecte) + {% else %} + {{ c.name }} + {% endif %} +
  • + {% endfor %} +
+
+ {% elsif var.default != nil %} +
+ Per defecte:
+ {{ var.default }} +
+ {% endif %} + {% if var.examples %} +

Exemples:

+ {% endif %} + {% for e in var.examples %} +
+

{{ forloop.index }}) {{ e.name }}

+{% highlight yaml %} +{{ e.code }} +{% endhighlight %} +
+ {% endfor %} +
diff --git a/i18n/ca/_build_forms/forms/index.md b/i18n/ca/_build_forms/forms/index.md new file mode 100644 index 0000000..4711dd8 --- /dev/null +++ b/i18n/ca/_build_forms/forms/index.md @@ -0,0 +1,87 @@ +--- +layout: default +title: Formularis +nav_order: 3 +has_children: true +has_toc: false +permalink: /forms/ +translated_from: 8cf41438dcd6f75b145856a890b8bbbcd674c9fc +--- + +# Formularis +{: .no_toc } + +Defineix els formularis que omplen els teus usuaris +{: .fs-6 .fw-300 } + +--- + +Per als autors de formularis: com s'escriuen els formularis en YAML, d'on es carreguen i les propietats de cada tipus de formulari. + +Els formularis són el nucli d'AnsibleForms. Cada formulari és una interfície web que recull les dades de l'usuari i, amb aquestes dades, executa un +playbook d'Ansible, una plantilla d'AWX, AAP o Ascender, una plantilla de Semaphore, un job de Rundeck o de Jenkins, o un +[workflow](../workflows/). + +Els formularis es defineixen en fitxers YAML a la carpeta de formularis. Cada fitxer YAML conté un sol formulari o una llista de formularis, i es poden fer servir subcarpetes per organitzar-los. + +**VÍDEO**: [Crea el teu primer formulari](https://www.youtube.com/watch?v=lIhYZ9Et5Ic) + +--- + +## Entendre l'estructura d'un formulari + +Cada formulari d'AnsibleForms es configura amb un conjunt de propietats. **[Propietats comunes](common.html)** recull les propietats que s'apliquen a tots els tipus de formulari; les pàgines específiques de cada tipus descriuen les addicionals. + +--- + +## Com es carreguen els formularis + +AnsibleForms carrega els formularis des de les ubicacions següents: + +1. **DES DELS REPOSITORIS**: tots els repositoris amb l'interruptor "Utilitzar per als formularis" activat (s'admeten diversos repositoris) + - Els formularis de tots els repositoris activats es fusionen automàticament. + - Primer es comprova si cada repositori té una subcarpeta `forms/`. + - Si no hi ha cap subcarpeta `forms/`, es fa servir l'arrel del repositori. + - Els formularis creats al dissenyador que encara no s'han enviat amb push es guarden en una carpeta de preparació + ([`FORMS_STAGING_PATH`](../customization/paths.html#env_FORMS_STAGING_PATH)) i es carreguen juntament amb els altres. + +2. **DES DE LA CARPETA LOCAL**: la carpeta local `forms/` + ([`FORMS_FOLDER_PATH`](../customization/paths.html#env_FORMS_FOLDER_PATH)), quan cap repositori no té activat "Utilitzar per als formularis" + +{: .warning } +> **Nota:** quan "Utilitzar per als formularis" està activat en diversos repositoris, se'n fusionen tots els formularis. Els noms dels formularis han de ser únics entre repositoris per evitar conflictes. + +--- + +## On s'executa un formulari + +El tipus d'un formulari decideix el tipus de [runner](../runners.html) on s'executa la seva tasca: un RTE per a `ansible`, un runner d'AWX per a `awx`, +`aap` i `ascender`, i un runner del seu mateix tipus per a `semaphore`, `rundeck` i `jenkins`. + +- `runner: ` al formulari tria pel nom un runner d'aquest tipus; sense això, la tasca s'executa al runner per defecte del tipus. +- Un runner desactivat a **Connexions > Runners** fa fallar la tasca, tant si el formulari l'anomena com si és el per defecte. La tasca + no recorre mai a un altre runner. +- Quan un dels rols de l'usuari inclou `runners` a `config.yaml`, la tasca només es pot executar en un runner que aquest rol inclogui, o es + rebutja. Els rols sense la llista no la limiten, i un administrador no està mai limitat. + +--- + +## En aquesta secció + +Les pàgines següents descriuen en detall les propietats dels formularis: + +| Pàgina | Què tracta | +|---|---| +| [Propietats comunes](common.html) | Propietats que s'apliquen a tots els tipus de formulari (`name`, `description`, `help`, `type`, `fields`) | +| [Formularis d'Ansible](ansible.html) | Propietats específiques de `type: ansible` | +| [Formularis d'AWX](awx.html) | Propietats específiques de `type: awx` | +| [Formularis de Semaphore](semaphore.html) | Propietats específiques de `type: semaphore`, que executa una plantilla de Semaphore | +| [Formularis de Rundeck](rundeck.html) | Propietats específiques de `type: rundeck`, que executa un job de Rundeck | +| [Formularis de Jenkins](jenkins.html) | Propietats específiques de `type: jenkins`, que fa un build d'un job de Jenkins | +| [Formularis multipas](multistep.html) | Propietats específiques de `type: multistep`, obsolet en favor de `workflow` | +| [Formularis de workflow](workflow.html) | Propietats específiques de `type: workflow`, que executa un [workflow](../workflows/) | +| [Assistent](wizard.html) | Repartir les dades d'un formulari en diverses pàgines (funciona sobre qualsevol tipus de formulari executable) | +| [Subformulari](subform.html) | Els subformularis només fan servir les propietats comunes | +| [Punts d'aprovació](approval.html) | Aturar una tasca fins que s'aprovi (`approval`) | +| [Notificacions](notifications.html) | Enviar correus i missatges a canals segons l'estat o els esdeveniments d'una tasca (`notifications`) | +| [Accions segons l'estat de la tasca](job-status-action.html) | Actuar sobre el formulari quan una tasca canvia d'estat (`onSubmit`, `onSuccess`, ...) | diff --git a/i18n/ca/_build_forms/forms/jenkins.md b/i18n/ca/_build_forms/forms/jenkins.md new file mode 100644 index 0000000..7e54a48 --- /dev/null +++ b/i18n/ca/_build_forms/forms/jenkins.md @@ -0,0 +1,110 @@ +--- +layout: default +title: Formularis de Jenkins +parent: Formularis +nav_order: 3.3 +translated_from: ff34be9b166e1c7956605787e9e6addc03bc2c57 +--- + +# Formularis de Jenkins +{: .no_toc } + +Formularis que fan un build d'un job de Jenkins +{: .fs-6 .fw-300 } + +--- + +{% assign help = site.data.help %} +{% assign formsyaml = help | where: "link", "forms" | first %} +{% assign form_object = formsyaml.help | where: "name", "Form" | first %} +{% assign type_prop = form_object.items | where: "name", "type" | first %} +{% assign jenkins_choice = type_prop.choices | where: "name", "jenkins" | first %} + +{{ jenkins_choice.description | markdownify }} + +{% if jenkins_choice.examples.size > 0 %} +{% for e in jenkins_choice.examples %} +**{{ e.name }}** +{% highlight yaml %} +{{ e.code }} +{% endhighlight %} +{% endfor %} +{% endif %} + +--- + +## Propietats + +Propietats específiques de `type: jenkins`, a més de les [propietats comunes dels formularis](common.html). + +{% assign jenkins_props = form_object.items | where_exp: "p", "p.with_types contains 'jenkins'" %} +{% assign jenkins_groups = jenkins_props | map: "group" | uniq | sort_natural %} +{% for group in jenkins_groups %} +{% assign group_props = jenkins_props | where: "group", group %} + +--- + +## {{ group | capitalize }} + + + + + + + + + + {% for var in group_props %} + + + + + {% endfor %} + +
AtributComentaris
+ {{ var.name }}
+ {{ var.type }} + {% if var.required == true %} / obligatori{% endif %} +
+ {% if var.version %}afegit a la versió {{ var.version }}{% endif %} +
+

+ {{ var.short }}
+ {% if var.allowed != nil %} + {{ var.allowed }} + {% endif %} +

+

{{ var.description | markdownify }}

+ {% if var.choices.size > 0 %} +
+ Opcions:
+
    + {% for c in var.choices %} +
  • + {% if c.name == var.default %} + {{ c.name }} (per defecte) + {% else %} + {{ c.name }} + {% endif %} +
  • + {% endfor %} +
+
+ {% elsif var.default != nil %} +
+ Per defecte: {{ var.default }} +
+ {% endif %} + {% if var.examples %} +

Exemples:

+ {% for e in var.examples %} +
+

{{ forloop.index }}) {{ e.name }}

+{% highlight yaml %} +{{ e.code }} +{% endhighlight %} +
+ {% endfor %} + {% endif %} +
+{% endfor %} diff --git a/i18n/ca/_build_forms/forms/job-status-action.md b/i18n/ca/_build_forms/forms/job-status-action.md new file mode 100644 index 0000000..e1fa412 --- /dev/null +++ b/i18n/ca/_build_forms/forms/job-status-action.md @@ -0,0 +1,86 @@ +--- +layout: default +title: Accions segons l'estat de la tasca +parent: Formularis +nav_order: 10 +translated_from: c374578652c98b4c2c68f068809f16c22e304147 +--- + +# Accions segons l'estat de la tasca +{: .no_toc } + +Actua sobre el formulari quan la seva tasca s'envia, té èxit, falla o acaba +{: .fs-6 .fw-300 } + +--- + +{% assign help = site.data.help %} +{% assign formsyaml = help | where: "link", "forms" | first %} +{% assign form_object = formsyaml.help | where: "name", "Form" | first %} +{% assign jobstatus_object = form_object.help | where: "name", "Job Status Action" | first %} + +{{ jobstatus_object.description | markdownify }} + +Hi ha disponibles els ganxos següents: + +- `onSubmit`: s'activa quan s'envia el formulari +- `onSuccess`: s'activa quan la tasca acaba correctament +- `onFailure`: s'activa quan la tasca falla +- `onFinish`: s'activa quan la tasca acaba, sigui quin sigui el seu estat +- `onAbort`: s'activa quan s'avorta la tasca + +--- + +## Atributs + +Els atributs d'una acció segons l'estat de la tasca: + + + + + + + + + + {% for var in jobstatus_object.items %} + + + + + {% endfor %} + +
AtributComentaris
+ {{ var.name }}
+ {{ var.type}} + {% if var.required==true %} / obligatori{% endif %} + {% if var.unique==true %} / únic{% endif %} +
+ {% if var.version %}afegit a la versió {{var.version}}{% endif %} +
+

+ {{var.short}}
+ {% if var.allowed != nil %} + {{ var.allowed }} + {% endif %} +

+

+ {{ var.description | markdownify }} +

+
+ +--- + +## Exemples + +Exemples d'accions segons l'estat de la tasca, en YAML: + +{% for example in jobstatus_object.examples %} +### {{ forloop.index }}) {{ example.name }} + +{% if example.description %}{{ example.description | markdownify }}{% elsif example.short %}{{ example.short }}{% else %}La definició, en YAML:{% endif %} + +```yaml +{{ example.code }} +``` +{% endfor %} diff --git a/i18n/ca/_build_forms/forms/multistep.md b/i18n/ca/_build_forms/forms/multistep.md new file mode 100644 index 0000000..c122020 --- /dev/null +++ b/i18n/ca/_build_forms/forms/multistep.md @@ -0,0 +1,240 @@ +--- +layout: default +title: Formularis multipas +parent: Formularis +nav_order: 5 +translated_from: b509f2f7365a2066cabfe1061fdb48c12c33ccbd +--- + +# Formularis multipas +{: .no_toc } + +Executa diversos playbooks o plantilles en seqüència des d'un sol formulari +{: .fs-6 .fw-300 } + +--- + +{: .warning } +> `multistep` està obsolet des de la 7 i s'elimina a la 8: fes servir un [workflow](workflow.html) en el seu lloc. Un workflow fa tot el que +> fa un multistep, amb condicions, valors propis per a cada node, nodes d'aprovació i branques que s'executen en paral·lel. + +{% assign help = site.data.help %} +{% assign formsyaml = help | where: "link", "forms" | first %} +{% assign form_object = formsyaml.help | where: "name", "Form" | first %} +{% assign type_prop = form_object.items | where: "name", "type" | first %} +{% assign multistep_choice = type_prop.choices | where: "name", "multistep" | first %} +{% assign step_object = form_object.help | where: "name", "Step" | first %} +{% assign steps_prop = form_object.items | where: "name", "steps" | first %} + +{{ multistep_choice.description | markdownify }} + +{% if multistep_choice.examples.size > 0 %} +{% for e in multistep_choice.examples %} +**{{ e.name }}** +{% highlight yaml %} +{{ e.code }} +{% endhighlight %} +{% endfor %} +{% endif %} + +--- + +## Propietat a nivell de formulari + +Un formulari multipas defineix els seus passos en una única propietat a nivell de formulari: + + + + + + + + + + + + + + +
AtributComentaris
+ {{ steps_prop.name }}
+ {{ steps_prop.type }} / obligatori +
+

{{ steps_prop.short }}

+ {{ steps_prop.description | markdownify }} +
+ +{% assign multistep_props = form_object.items | where_exp: "p", "p.with_types contains 'multistep'" %} + +A més de `steps`, un formulari multipas accepta aquestes propietats a nivell de formulari, documentades a la pàgina [Formularis d'Ansible](ansible.html): +{% for p in multistep_props %}{% if p.name != "steps" %}[`{{ p.name }}`](ansible.html#ansible_{{ p.name }}){% if p.required == true %} (obligatòria){% endif %}{% unless forloop.last %}, {% endunless %}{% endif %}{% endfor %}. + +--- + +## Propietats dels passos + +{{ step_object.description | markdownify }} + + + + + + + + + + {% assign groups = step_object.items | map: "group" | uniq | sort_natural %} + {% for group in groups %} + {% assign group_properties = step_object.items | where: "group",group %} + {% if group %} + + + + {% endif %} + {% for var in group_properties %} + + + + + {% endfor %} + {% endfor %} + {% if step_object.examples %} + + + + + + + {% endif %} + +
AtributComentaris
+ {{ group }} +
+ {{ var.name }}
+ {{ var.type}} + {% if var.required==true %} / obligatori{% endif %} + {% if var.unique==true %} / únic{% endif %} +
+ {% if var.version %}afegit a la versió {{var.version}}{% endif %} +
+

+ {{var.short}}
+ {% if var.allowed != nil %} + {{ var.allowed }} + {% endif %} +

+

+ {{ var.description | markdownify }} +

+ {% if var.choices.size > 0 %} +
+ Opcions:
+
    + {% for c in var.choices %} +
  • + {% if c.name == var.default %} + {{ c.name }} (per defecte) + {% else %} + {{ c.name }} + {% endif %} +
  • + {% endfor %} +
+
+ {% elsif var.default != nil %} +
+ Per defecte:
+ {{ var.default }} +
+ {% endif %} + {% if var.with_types!=nil %} +
+ Només disponible amb els tipus:
+ {{ var.with_types }} +

+
+ {% endif %} + {% for c in var.changelog %} +
+ {% if c.type == "added" %} +
+ Afegit + {{ c.version }} +
+ {% endif %} +

+ {{ c.description | markdownify }} +

+
+ {% endfor %} + {% if var.examples %} +

Exemples:

+ {% endif %} + {% for e in var.examples %} +
+

{{ forloop.index }}) {{ e.name }}

+{% highlight yaml %} +{{ e.code }} +{% endhighlight %} +
+ {% endfor %} +
+ Exemples +
+ {% for e in step_object.examples %} +
+

{{ forloop.index }}) {{ e.name }}

+{% highlight yaml %} +{{ e.code }} +{% endhighlight %} +
+ {% endfor %} +
+ +--- + +## Exemple + +Un formulari multipas executa diverses tasques en seqüència, i cada pas llança el seu propi playbook o plantilla d'AWX. Tots els passos comparteixen els camps del formulari: per defecte, cada pas rep totes les extravars, i la `key` d'un pas el limita a aquesta part. + +### Crear i configurar un servidor + +Cada pas rep la seva pròpia part de les extravars: un pas d'AWX crea el servidor, un pas d'Ansible en configura la xarxa i un últim pas sempre envia un informe: + +```yaml +name: Server Provisioning +type: multistep +roles: + - default +categories: + - Setup +steps: + - name: Create server + type: awx + template: Create VM + key: server # receives only the `server` part of the extravars + - name: Configure network + type: ansible + playbook: configure_network.yml + key: network # receives only the `network` part of the extravars + - name: Send report + type: ansible + playbook: email.yml + always: true # runs even when an earlier step failed +fields: + - name: server_name + type: text + model: server.name + - name: environment + type: enum + values: + - dev + - prod + model: server.environment + - name: ip_address + type: text + model: network.ip + - name: gateway + type: text + model: network.gateway +``` diff --git a/i18n/ca/_build_forms/forms/notifications.md b/i18n/ca/_build_forms/forms/notifications.md new file mode 100644 index 0000000..467c8df --- /dev/null +++ b/i18n/ca/_build_forms/forms/notifications.md @@ -0,0 +1,120 @@ +--- +layout: default +title: Notificacions +parent: Formularis +nav_order: 9 +translated_from: 3c44a310353f7884a0d2d1e3a827f8a757f7d25d +--- + +# Notificacions +{: .no_toc } + +Envia un correu o un missatge a un canal quan una tasca acaba o li passa alguna cosa +{: .fs-6 .fw-300 } + +--- + +Les `notifications` d'un formulari indiquen qui s'assabenta de les seves tasques, i quan: + +- **Qui**: `recipients`, adreces de correu electrònic, i `channels`, els noms dels + [canals de notificació](../notification-channels.html) (correu, Slack, Microsoft Teams, Telegram, un webhook). Cal com a mínim + un dels dos. +- **Quan**: `onStatus`, quan una tasca acaba (`success`, `failed`, `aborted`, `warning` o `any`), i `onEvent`, quan + li passa alguna cosa a una tasca (`launch`, `relaunch`, `delete`, `approve`, `reject` o `any`). + +```yaml +notifications: + recipients: + - ops@example.com + channels: + - ops-teams + onStatus: + - failed + onEvent: + - approve + - reject +``` + +{% assign help = site.data.help %} +{% assign formsyaml = help | where: "link", "forms" | first %} +{% assign form_object = formsyaml.help | where: "name", "Form" | first %} +{% assign notifications_object = form_object.help | where: "name", "Notifications" | first %} + +{{ notifications_object.description | markdownify }} + +--- + +## Atributs + +Els atributs de l'objecte `notifications`: + + + + + + + + + + {% for var in notifications_object.items %} + + + + + {% endfor %} + +
AtributComentaris
+ {{ var.name }}
+ {{ var.type}} + {% if var.required==true %} / obligatori{% endif %} + {% if var.unique==true %} / únic{% endif %} +
+ {% if var.version %}afegit a la versió {{var.version}}{% endif %} +
+

+ {{var.short}}
+ {% if var.allowed != nil %} + {{ var.allowed }} + {% endif %} +

+

+ {{ var.description | markdownify }} +

+ {% if var.choices.size > 0 %} +
+ Opcions:
+
    + {% for c in var.choices %} +
  • + {% if c.name == var.default %} + {{ c.name }} (per defecte) + {% else %} + {{ c.name }} + {% endif %} +
  • + {% endfor %} +
+
+ {% elsif var.default != nil %} +
+ Per defecte:
+ {{ var.default }} +
+ {% endif %} +
+ +--- + +## Exemples + +Exemples de notificacions, en YAML: + +{% for example in notifications_object.examples %} +### {{ forloop.index }}) {{ example.name }} + +{% if example.description %}{{ example.description | markdownify }}{% elsif example.short %}{{ example.short }}{% else %}La definició, en YAML:{% endif %} + +```yaml +{{ example.code }} +``` +{% endfor %} diff --git a/i18n/ca/_build_forms/forms/rundeck.md b/i18n/ca/_build_forms/forms/rundeck.md new file mode 100644 index 0000000..0aa606a --- /dev/null +++ b/i18n/ca/_build_forms/forms/rundeck.md @@ -0,0 +1,110 @@ +--- +layout: default +title: Formularis de Rundeck +parent: Formularis +nav_order: 3.2 +translated_from: 2ea4d32ab60fa14c631358d16bc118485437ecb1 +--- + +# Formularis de Rundeck +{: .no_toc } + +Formularis que executen un job de Rundeck +{: .fs-6 .fw-300 } + +--- + +{% assign help = site.data.help %} +{% assign formsyaml = help | where: "link", "forms" | first %} +{% assign form_object = formsyaml.help | where: "name", "Form" | first %} +{% assign type_prop = form_object.items | where: "name", "type" | first %} +{% assign rundeck_choice = type_prop.choices | where: "name", "rundeck" | first %} + +{{ rundeck_choice.description | markdownify }} + +{% if rundeck_choice.examples.size > 0 %} +{% for e in rundeck_choice.examples %} +**{{ e.name }}** +{% highlight yaml %} +{{ e.code }} +{% endhighlight %} +{% endfor %} +{% endif %} + +--- + +## Propietats + +Propietats específiques de `type: rundeck`, a més de les [propietats comunes dels formularis](common.html). + +{% assign rundeck_props = form_object.items | where_exp: "p", "p.with_types contains 'rundeck'" %} +{% assign rundeck_groups = rundeck_props | map: "group" | uniq | sort_natural %} +{% for group in rundeck_groups %} +{% assign group_props = rundeck_props | where: "group", group %} + +--- + +## {{ group | capitalize }} + + + + + + + + + + {% for var in group_props %} + + + + + {% endfor %} + +
AtributComentaris
+ {{ var.name }}
+ {{ var.type }} + {% if var.required == true %} / obligatori{% endif %} +
+ {% if var.version %}afegit a la versió {{ var.version }}{% endif %} +
+

+ {{ var.short }}
+ {% if var.allowed != nil %} + {{ var.allowed }} + {% endif %} +

+

{{ var.description | markdownify }}

+ {% if var.choices.size > 0 %} +
+ Opcions:
+
    + {% for c in var.choices %} +
  • + {% if c.name == var.default %} + {{ c.name }} (per defecte) + {% else %} + {{ c.name }} + {% endif %} +
  • + {% endfor %} +
+
+ {% elsif var.default != nil %} +
+ Per defecte: {{ var.default }} +
+ {% endif %} + {% if var.examples %} +

Exemples:

+ {% for e in var.examples %} +
+

{{ forloop.index }}) {{ e.name }}

+{% highlight yaml %} +{{ e.code }} +{% endhighlight %} +
+ {% endfor %} + {% endif %} +
+{% endfor %} diff --git a/i18n/ca/_build_forms/forms/semaphore.md b/i18n/ca/_build_forms/forms/semaphore.md new file mode 100644 index 0000000..fa3a03e --- /dev/null +++ b/i18n/ca/_build_forms/forms/semaphore.md @@ -0,0 +1,110 @@ +--- +layout: default +title: Formularis de Semaphore +parent: Formularis +nav_order: 3.1 +translated_from: 34f55c2309cb70bf641b642cafc27b0e703c89e6 +--- + +# Formularis de Semaphore +{: .no_toc } + +Formularis que executen una plantilla de Semaphore UI +{: .fs-6 .fw-300 } + +--- + +{% assign help = site.data.help %} +{% assign formsyaml = help | where: "link", "forms" | first %} +{% assign form_object = formsyaml.help | where: "name", "Form" | first %} +{% assign type_prop = form_object.items | where: "name", "type" | first %} +{% assign semaphore_choice = type_prop.choices | where: "name", "semaphore" | first %} + +{{ semaphore_choice.description | markdownify }} + +{% if semaphore_choice.examples.size > 0 %} +{% for e in semaphore_choice.examples %} +**{{ e.name }}** +{% highlight yaml %} +{{ e.code }} +{% endhighlight %} +{% endfor %} +{% endif %} + +--- + +## Propietats + +Propietats específiques de `type: semaphore`, a més de les [propietats comunes dels formularis](common.html). + +{% assign semaphore_props = form_object.items | where_exp: "p", "p.with_types contains 'semaphore'" %} +{% assign semaphore_groups = semaphore_props | map: "group" | uniq | sort_natural %} +{% for group in semaphore_groups %} +{% assign group_props = semaphore_props | where: "group", group %} + +--- + +## {{ group | capitalize }} + + + + + + + + + + {% for var in group_props %} + + + + + {% endfor %} + +
AtributComentaris
+ {{ var.name }}
+ {{ var.type }} + {% if var.required == true %} / obligatori{% endif %} +
+ {% if var.version %}afegit a la versió {{ var.version }}{% endif %} +
+

+ {{ var.short }}
+ {% if var.allowed != nil %} + {{ var.allowed }} + {% endif %} +

+

{{ var.description | markdownify }}

+ {% if var.choices.size > 0 %} +
+ Opcions:
+
    + {% for c in var.choices %} +
  • + {% if c.name == var.default %} + {{ c.name }} (per defecte) + {% else %} + {{ c.name }} + {% endif %} +
  • + {% endfor %} +
+
+ {% elsif var.default != nil %} +
+ Per defecte: {{ var.default }} +
+ {% endif %} + {% if var.examples %} +

Exemples:

+ {% for e in var.examples %} +
+

{{ forloop.index }}) {{ e.name }}

+{% highlight yaml %} +{{ e.code }} +{% endhighlight %} +
+ {% endfor %} + {% endif %} +
+{% endfor %} diff --git a/i18n/ca/_build_forms/forms/subform.md b/i18n/ca/_build_forms/forms/subform.md new file mode 100644 index 0000000..1750706 --- /dev/null +++ b/i18n/ca/_build_forms/forms/subform.md @@ -0,0 +1,49 @@ +--- +layout: default +title: Subformulari +parent: Formularis +nav_order: 4 +translated_from: 25524e14dc072b76c778d7f92adbfbc5f82d3519 +--- + +# Subformulari +{: .no_toc } + +Un fragment de formulari reutilitzable per a camps list, camps yaml i pàgines d'assistent +{: .fs-6 .fw-300 } + +--- + +Un subformulari és un fragment de formulari reutilitzable. No apareix a la vista de mosaic i no es pot enviar directament. En lloc d'això, s'hi fa referència des de: + +- Un camp [`list`](../formfields/list.html): obre el subformulari com a editor de detall per a cada fila +- Un camp [`yaml`](../formfields/yaml.html) amb la propietat `subform`: obre el subformulari com a editor de detall per a un sol objecte +- Un pas d'un [`wizard`](wizard.html): mostra el subformulari com una pàgina de l'assistent + +{% assign help = site.data.help %} +{% assign formsyaml = help | where: "link", "forms" | first %} +{% assign form_object = formsyaml.help | where: "name", "Form" | first %} +{% assign type_prop = form_object.items | where: "name", "type" | first %} +{% assign subform_choice = type_prop.choices | where: "name", "subform" | first %} + +{{ subform_choice.description | markdownify }} + +{% if subform_choice.examples.size > 0 %} +{% for e in subform_choice.examples %} +**{{ e.name }}** +{% highlight yaml %} +{{ e.code }} +{% endhighlight %} +{% endfor %} +{% endif %} + +--- + +## Propietats + +Els subformularis **no tenen propietats específiques del tipus**. Només fan servir les [propietats comunes dels formularis](common.html): `name`, `description`, `help`, `type` i `fields`. + +Quan un subformulari fa de pàgina d'un assistent, el seu `description` i el seu `help` proporcionen els valors per defecte del `title` i el `help` del pas. També pot definir `showHelp` per desplegar aquesta ajuda quan es carrega la pàgina. + +Les propietats d'execució (`playbook`, `template`, `roles`, `inventory`, etc.) no s'apliquen als subformularis, perquè un subformulari no s'envia mai directament. + diff --git a/i18n/ca/_build_forms/forms/wizard.md b/i18n/ca/_build_forms/forms/wizard.md new file mode 100644 index 0000000..33510aa --- /dev/null +++ b/i18n/ca/_build_forms/forms/wizard.md @@ -0,0 +1,210 @@ +--- +layout: default +title: Assistent +parent: Formularis +nav_order: 7 +translated_from: aec059391571165259ed43449b0450d0ef7f6cf2 +--- + +# Assistent +{: .no_toc } + +Reparteix les dades d'un formulari en diverses pàgines amb Enrere i Següent +{: .fs-6 .fw-300 } + +--- + +{% assign help = site.data.help %} +{% assign formsyaml = help | where: "link", "forms" | first %} +{% assign form_object = formsyaml.help | where: "name", "Form" | first %} +{% assign wizard_prop = form_object.items | where: "name", "wizard" | first %} +{% assign wizard_object = form_object.help | where: "name", "Wizard step" | first %} + +--- + +## Què és un assistent? + +Un **assistent** (`wizard`) converteix un sol formulari en una seqüència de pàgines. Cada pàgina es genera a partir d'un [`subform`](subform.html) i l'usuari hi navega amb els botons **Enrere** i **Següent**. La validació s'aplica pàgina per pàgina: l'usuari no pot avançar fins que el pas actual sigui vàlid, tret que el pas estigui marcat com a `optional`. + +Al final de cada assistent s'hi afegeix automàticament una **pàgina de revisió** de només lectura. Mostra cada pas amb els valors recollits perquè l'usuari els pugui confirmar abans d'enviar. La pàgina de revisió **no** es declara en YAML; el seu títol surt de l'idioma actiu. + +En enviar, els **valors recollits de tots els passos es fusionen en un sol conjunt d'extravars** i s'envien al playbook, la plantilla o el workflow subjacent, exactament com si l'usuari hagués omplert un únic formulari gran. + +Un formulari amb un `wizard` no necessita `fields` propis, però no pot definir `enableForChat`, i un `subform` no pot tenir un `wizard` propi. La [validació del llançament](../launch-validation/rolling-it-out.html#wizard-forms) comprova el llançament d'un assistent pas a pas. + +{: .note } +> Per saber en què es diferencia un `wizard` d'un workflow, i com es combinen, consulta l'entrada de les PMF [Quina diferència hi ha entre un assistent i un workflow?](../faq.html#what-is-the-difference-between-a-wizard-and-a-workflow). + +--- + +## Propietat a nivell de formulari + +Un assistent s'activa amb una única propietat a nivell de formulari: + + + + + + + + + + + + + + +
AtributComentaris
+ {{ wizard_prop.name }}
+ {{ wizard_prop.type }} + {% if wizard_prop.version %}
afegit a la versió {{ wizard_prop.version }}{% endif %} +
+

{{ wizard_prop.short }}

+ {{ wizard_prop.description | markdownify }} +
+ +{% if wizard_prop.examples %} +**Exemples:** +{% for e in wizard_prop.examples %} + +*{{ forloop.index }}) {{ e.name }}* +{% highlight yaml %} +{{ e.code }} +{% endhighlight %} +{% endfor %} +{% endif %} + +--- + +## Propietats dels passos de l'assistent + +{{ wizard_object.description | markdownify }} + + + + + + + + + + {% assign groups = wizard_object.items | map: "group" | uniq | sort_natural %} + {% for group in groups %} + {% assign group_properties = wizard_object.items | where: "group",group %} + {% if group %} + + + + {% endif %} + {% for var in group_properties %} + + + + + {% endfor %} + {% endfor %} + {% if wizard_object.examples %} + + + + + + + {% endif %} + +
AtributComentaris
+ {{ group }} +
+ {{ var.name }}
+ {{ var.type}} + {% if var.required==true %} / obligatori{% endif %} + {% if var.unique==true %} / únic{% endif %} +
+ {% if var.version %}afegit a la versió {{var.version}}{% endif %} +
+

+ {{var.short}}
+ {% if var.allowed != nil %} + {{ var.allowed }} + {% endif %} +

+

+ {{ var.description | markdownify }} +

+ {% if var.choices.size > 0 %} +
+ Opcions:
+
    + {% for c in var.choices %} +
  • + {% if c.name == var.default %} + {{ c.name }} (per defecte) + {% else %} + {{ c.name }} + {% endif %} +
  • + {% endfor %} +
+
+ {% elsif var.default != nil %} +
+ Per defecte:
+ {{ var.default }} +
+ {% endif %} + {% for c in var.changelog %} +
+ {% if c.type == "added" %} +
+ Afegit + {{ c.version }} +
+ {% endif %} +

+ {{ c.description | markdownify }} +

+
+ {% endfor %} + {% if var.examples %} +

Exemples:

+ {% endif %} + {% for e in var.examples %} +
+

{{ forloop.index }}) {{ e.name }}

+{% highlight yaml %} +{{ e.code }} +{% endhighlight %} +
+ {% endfor %} +
+ Exemples +
+ {% for e in wizard_object.examples %} +
+

{{ forloop.index }}) {{ e.name }}

+{% highlight yaml %} +{{ e.code }} +{% endhighlight %} +
+ {% endfor %} +
+ +--- + +## Combinar un assistent amb un workflow + +Un assistent es pot posar per sobre d'un formulari de [workflow](workflow.html). Quan el `defaultModel` de cada pas de l'assistent coincideix amb l'[`extra_vars_key`](../workflows/file.html#ansibleforms-own-keys) del node corresponent del workflow, cada playbook o plantilla rep només els valors de la seva pròpia pàgina de l'assistent. + +Les PMF contenen un exemple complet i l'estructura de les extravars fusionades: [Quina diferència hi ha entre un assistent i un workflow?](../faq.html#what-is-the-difference-between-a-wizard-and-a-workflow) (secció *Combinat (assistent per sobre d'un workflow)*). + +Un assistent en un formulari [`multistep`](multistep.html), que està obsolet, funciona de la mateixa manera, amb la [`key`](multistep.html#step_key) del pas en lloc d'`extra_vars_key`. + +--- + +## Vegeu també + +Pàgines relacionades i entrades de les PMF: + +- [Subformulari](subform.html): les pàgines de l'assistent es generen a partir de subformularis +- [Formularis de workflow](workflow.html): l'equivalent de l'assistent a la capa d'execució +- [`__parent__` als subformularis](../faq.html#how-do-i-access-parent-form-data-inside-a-subform): com fer referència als passos anteriors de l'assistent des d'un pas posterior diff --git a/i18n/ca/_build_forms/forms/workflow.md b/i18n/ca/_build_forms/forms/workflow.md new file mode 100644 index 0000000..eeebe16 --- /dev/null +++ b/i18n/ca/_build_forms/forms/workflow.md @@ -0,0 +1,111 @@ +--- +layout: default +title: Formularis de workflow +parent: Formularis +nav_order: 6 +translated_from: 84ff9fbe71945ce4437cf82034f80a6bfa8b3691 +--- + +# Formularis de workflow +{: .no_toc } + +Formularis que executen un dels workflows del dissenyador +{: .fs-6 .fw-300 } + +--- + +{% assign help = site.data.help %} +{% assign formsyaml = help | where: "link", "forms" | first %} +{% assign form_object = formsyaml.help | where: "name", "Form" | first %} +{% assign type_prop = form_object.items | where: "name", "type" | first %} +{% assign workflow_choice = type_prop.choices | where: "name", "workflow" | first %} + +{{ workflow_choice.description | markdownify }} + +{% if workflow_choice.examples.size > 0 %} +{% for e in workflow_choice.examples %} +**{{ e.name }}** +{% highlight yaml %} +{{ e.code }} +{% endhighlight %} +{% endfor %} +{% endif %} + +--- + +## Propietats + +Propietats específiques de `type: workflow`, a més de les [propietats comunes dels formularis](common.html). La secció +[Workflows](../workflows/) descriu els fitxers de workflow en si. + +{% assign workflow_props = form_object.items | where_exp: "p", "p.with_types contains 'workflow'" %} +{% assign workflow_groups = workflow_props | map: "group" | uniq | sort_natural %} +{% for group in workflow_groups %} +{% assign group_props = workflow_props | where: "group", group %} + +--- + +## {{ group | capitalize }} + + + + + + + + + + {% for var in group_props %} + + + + + {% endfor %} + +
AtributComentaris
+ {{ var.name }}
+ {{ var.type }} + {% if var.required == true %} / obligatori{% endif %} +
+ {% if var.version %}afegit a la versió {{ var.version }}{% endif %} +
+

+ {{ var.short }}
+ {% if var.allowed != nil %} + {{ var.allowed }} + {% endif %} +

+

{{ var.description | markdownify }}

+ {% if var.choices.size > 0 %} +
+ Opcions:
+
    + {% for c in var.choices %} +
  • + {% if c.name == var.default %} + {{ c.name }} (per defecte) + {% else %} + {{ c.name }} + {% endif %} +
  • + {% endfor %} +
+
+ {% elsif var.default != nil %} +
+ Per defecte: {{ var.default }} +
+ {% endif %} + {% if var.examples %} +

Exemples:

+ {% for e in var.examples %} +
+

{{ forloop.index }}) {{ e.name }}

+{% highlight yaml %} +{{ e.code }} +{% endhighlight %} +
+ {% endfor %} + {% endif %} +
+{% endfor %} diff --git a/i18n/ca/_build_forms/launch-validation/file-uploads.md b/i18n/ca/_build_forms/launch-validation/file-uploads.md new file mode 100644 index 0000000..3a5f0f5 --- /dev/null +++ b/i18n/ca/_build_forms/launch-validation/file-uploads.md @@ -0,0 +1,63 @@ +--- +layout: default +title: Pujades de fitxers +parent: Validació del llançament +nav_order: 4 +translated_from: 5756d90b62ddac51996f0bdb05befd6bf5589e0d +--- + +# Pujades de fitxers +{: .no_toc } + +Com es validen els camps de fitxer +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +Un camp de fitxer no es fia mai del que diu la petició de llançament sobre un fitxer. La validació del llançament comprova el fitxer mateix, al +disc del servidor. + +--- + +## Com arriba una pujada a una tasca + +Un fitxer es puja abans de llançar el formulari, en dos passos: + +1. El navegador puja el fitxer amb `POST /api/v2/job/upload`. El servidor el desa a `UPLOAD_PATH`. +2. La petició de llançament descriu aquesta pujada a la seva part `files`. + +Després, la validació del llançament compara la descripció amb el disc: + +* El fitxer ha d'existir dins d'`UPLOAD_PATH`. +* El seu camí i la seva mida es llegeixen del disc, mai de la petició. + +--- + +## Què s'accepta + +Un camp de fitxer només obté un valor d'una pujada verificada. Qualsevol altra cosa es descarta: + +* Un camí que qui fa la crida escrigui a `rawFormData` o a `extravars` s'ignora. +* Un camp de fitxer obligatori sense una pujada real es notifica com a `missing`. + +--- + +## Regles de fitxer + +Les regles d'un camp de fitxer es comproven amb la pujada real, amb les mides en bytes: + +```yaml +- name: firmware + type: file + required: true + maxSize: 104857600 # 100 MB + regex: + expression: '\.bin$' + description: Upload a .bin firmware image +``` + +`minSize` i `maxSize` comparen la mida real del fitxer, i `regex`, el seu nom. Independentment de qualsevol formulari, +`UPLOAD_MAX_GB` limita la mida d'una sola pujada (10 GB per defecte). diff --git a/i18n/ca/_build_forms/launch-validation/index.md b/i18n/ca/_build_forms/launch-validation/index.md new file mode 100644 index 0000000..5bf168a --- /dev/null +++ b/i18n/ca/_build_forms/launch-validation/index.md @@ -0,0 +1,78 @@ +--- +layout: default +title: Validació del llançament +nav_order: 4 +has_children: true +has_toc: false +permalink: /launch-validation/ +translated_from: 6b86704480781edc0ab1c24c25993fc2e220abf3 +--- + +# Validació del llançament +{: .no_toc } + +Comprova al servidor cada llançament d'un formulari +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +Per a administradors i autors de formularis: fes que el servidor comprovi cada llançament, les seves regles i les seves extravars, l'enviï qui l'enviï. + +La comprovació s'aplica sigui qui sigui o sigui el que sigui que llanci el formulari: el navegador, un script que crida l'API REST +o un agent d'IA a través del servidor MCP. + +--- + +## Per què existeix + +Les regles d'un formulari (`required`, `regex`, `minValue`, `sameAs`, ...) sempre s'han comprovat +al navegador. Després, el navegador envia dues coses a `POST /api/v2/job`: + +- `rawFormData`: els valors dels camps tal com els ha omplert l'usuari; +- `extravars`: el que rep el playbook, construït al navegador a partir d'aquests valors. + +Sense la validació del llançament, el servidor es fia de totes dues. Qualsevol persona amb un token vàlid pot cridar aquest +punt final directament i enviar-hi qualsevol extravar, sense que s'apliqui cap regex, camp obligatori ni regla de +llista. Per a un formulari que només es fa servir al navegador, això pot ser acceptable; per a un +formulari que altres sistemes llancen per REST, vol dir que les regles del formulari no s'apliquen en absolut. + +A més, el servidor no té manera de distingir una petició del navegador d'una enviada per un +script: totes dues fan servir el mateix punt final, el mateix token i el mateix cos, i els usuaris poden modificar +qualsevol petició que enviï el seu propi navegador. Només es pot confiar en una comprovació feta al servidor, i la validació +del llançament és aquesta comprovació. + +--- + +## Les tres vies d'entrada + +La manera com es valida un llançament depèn de per on arriba i del mode de validació del llançament: + +| Llançat per | Validat | Extravars amb què s'executa la tasca | +|---|---|---| +| **Servidor MCP** (agent d'IA) | sempre, al servidor | sempre construïdes pel servidor | +| **Navegador** o **API REST**, validació del llançament `off` | només al navegador | les que ha enviat el navegador (o qui fa la crida) | +| **Navegador** o **API REST**, validació del llançament `log` | al servidor, els rebuigs només es registren | les enviades; les diferències es registren | +| **Navegador** o **API REST**, validació del llançament `enforce` | al servidor, es rebutja si no és vàlid | **construïdes pel servidor** | + +El navegador, el servidor MCP i la validació del llançament fan servir el mateix codi per a les regles (el +motor de formularis compartit): les mateixes regles, en el mateix ordre i amb els mateixos missatges. Un error que +mostra el navegador, el servidor el rebutja amb el mateix text. + +--- + +## En aquesta secció + +Cada tema té la seva pròpia pàgina: + +| Pàgina | Què tracta | +|---|---| +| [Activar-la](switching-it-on.html) | Per a tota la instància, o per a un formulari | +| [Registrar i aplicar](log-and-enforce.html) | Què fa cada mode amb un llançament que incompleix les regles | +| [Files de llista](list-rows-and-subforms.html) | Com es validen les files dels camps list | +| [Pujades de fitxers](file-uploads.html) | Com es validen els camps de fitxer | +| [Contrasenyes](passwords.html) | Com es validen els camps de contrasenya i com es mantenen fora de les API | +| [Rellançament](relaunching.html) | Com es valida una tasca rellançada | +| [Desplegar-la](rolling-it-out.html) | Passar una instància a enforce, i les limitacions conegudes | diff --git a/i18n/ca/_build_forms/launch-validation/list-rows-and-subforms.md b/i18n/ca/_build_forms/launch-validation/list-rows-and-subforms.md new file mode 100644 index 0000000..c6468b6 --- /dev/null +++ b/i18n/ca/_build_forms/launch-validation/list-rows-and-subforms.md @@ -0,0 +1,58 @@ +--- +layout: default +title: Files de llista +parent: Validació del llançament +nav_order: 3 +translated_from: 2f28c42b47c253f87a9be9d5b1bd8638f7dca685 +--- + +# Files de llista +{: .no_toc } + +Com es validen les files dels camps list +{: .fs-6 .fw-300 } + +--- + +Un camp `list` conté files; cada fila és una instància del seu subformulari, emplenada amb l'editor +de files. Un camp `yaml` amb un `subform` és una d'aquestes files. El servidor les tracta de la mateixa manera +que l'editor de files del navegador: cada fila es resol a través del seu subformulari, amb els valors del formulari +com a `__parent__`, se'n comproven les regles i se n'avaluen els camps calculats. Les llistes niades funcionen +igual: dins de la llista pròpia d'una fila, `$(__parent__.__parent__.x)` arriba fins al formulari. + +Les files es comproven així: + +- **Una fila que l'usuari ha afegit o editat** a l'editor es resol i es valida. +- **Una fila que ningú no ha tocat**, generada pel valor per defecte, l'expressió o la consulta de la mateixa llista + (com ara les entrades existents d'una llista d'ACL), passa **exactament tal com ha arribat**, igual que al + navegador: no es torna a validar i no s'hi afegeix res. Una entrada existent que incompleix una regla + escrita més tard no atura el llançament. +- **Una fila marcada com a eliminada** (el `deleteMarker` de la llista) es conserva tal com és i no es valida. + +Per distingir aquestes files sense fiar-se de la petició, el servidor torna a executar la font de la +llista (el seu valor per defecte o, si no, la seva expressió o consulta) sota la validació del llançament. Una fila +que no ha passat per l'editor passa sense canvis **només si és una de les files que genera +aquesta font**. Qualsevol altra fila, com ara una que s'inventi qui fa una crida REST, es resol i es +valida com una fila editada. Per tant, una fila senzilla no es pot saltar les comprovacions, mentre que les +files no tocades del navegador continuen passant sense canvis. + +Un usuari del navegador només ho nota en un cas: les dades de la font han canviat entre que s'ha obert el +formulari i que s'ha llançat (mentrestant s'ha canviat o eliminat una entrada), **i** aquesta fila +incompleix una regla del seu subformulari. Llavors la fila ja no compta com una de les files de la font, de manera que +es valida, i el llançament es rebutja indicant la fila, per exemple +`acls[2].user_or_group (regex)`. + +Les files que fallen apareixen a `rowErrors` amb el seu `index` (un camp `yaml` no en té) i al registre com a +`disks[1].size (maxValue)`. + +Un llançament pot contenir com a màxim **500 files** sumant tots els nivells de niament, ja que cada fila executa les consultes del seu subformulari. + +--- + +## Marcadors de fila + +Els marcadors que una llista posa a les seves files (`insertMarker`, `updateMarker` i `deleteMarker`; sense +`insertMarker`, les files noves reben `__inserted__` quan la llista defineix `allowDelete: false`, un `deleteMarker` o un `updateMarker`) +arriben al playbook en cada fila que en porta un. Una fila eliminada s'envia amb el seu marcador +d'eliminació, perquè el playbook la pugui eliminar. Abans de la 6.4.1, una fila de llista només portava un marcador si el seu +subformulari el declarava com a camp (ocult). diff --git a/i18n/ca/_build_forms/launch-validation/log-and-enforce.md b/i18n/ca/_build_forms/launch-validation/log-and-enforce.md new file mode 100644 index 0000000..df8df52 --- /dev/null +++ b/i18n/ca/_build_forms/launch-validation/log-and-enforce.md @@ -0,0 +1,108 @@ +--- +layout: default +title: Registrar i aplicar +parent: Validació del llançament +nav_order: 2 +translated_from: 10a187b350155ce68bfc50e379e1b6b8637df57a +--- + +# Registrar i aplicar +{: .no_toc } + +Què fa cada mode amb un llançament que incompleix les regles +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +## Què fa `log` + +Es comprova cada llançament, però per a l'usuari no canvia res. S'escriu un avís al registre quan: + +- el llançament **es rebutjaria**, amb el motiu (només noms de camp i tipus de regla, mai + valors): + + ``` + Launch validation would refuse form 'Create VM' for alice (launch validation 'log') : + failing rules : hostname (regex) ; failing rows : disks[1].size (maxValue) + ``` + +- les extravars que ha enviat el client **difereixen** de les que construeix el servidor, amb les + claus de primer nivell que difereixen: + + ``` + Launch of form 'Create VM' : the extravars differ from the ones the server builds for + created_at, vm (launch validation 'log' ; 'enforce' would run the server's) + ``` + +Primer, fes funcionar `log` durant un temps en una instància real. Mostra quins formularis es rebutjarien i +quins calculen valors diferents al servidor, abans que afecti ningú. + +--- + +## Què fa `enforce` + +Amb `enforce`, un llançament no vàlid es rebutja, i un de vàlid s'executa amb les extravars que construeix +el servidor. + +### Un llançament que incompleix les regles es rebutja + +`POST /api/v2/job` respon `422` amb els camps que fallen: + +```json +{ + "error": "The form data is not valid", + "details": { + "missing": ["owner"], + "invalid": ["hostname", "disks"], + "waiting": [], + "validationErrors": { + "hostname": [{ "type": "regex", "description": "Must start with prod-" }] + }, + "rowErrors": { + "disks": [{ "index": 1, "invalid": ["size"], + "validationErrors": { "size": [{ "type": "maxValue", "description": "size must be at most 500" }] } }] + } + } +} +``` + +- `missing`: camps obligatoris sense valor; +- `invalid`: camps que incompleixen una regla, opcions que no són cap de les permeses i camps list + amb alguna fila que falla; +- `waiting`: camps que no s'han pogut avaluar (un camp que necessiten no ha arribat a tenir valor); +- `validationErrors`: per a cada camp, totes les regles que fallen amb el missatge que mostra el navegador; +- `rowErrors`: per a cada camp list, les files que fallen (vegeu [Files de llista](list-rows-and-subforms.html)); +- `uploads`: camps de fitxer la pujada dels quals no s'ha pogut verificar. + +Un llançament **sense `rawFormData`** també es rebutja: els seus valors no es poden comprovar. + +### Un llançament vàlid s'executa amb les extravars del servidor + +La tasca no s'executa amb les extravars que ha enviat el client. El servidor les construeix a partir dels valors +comprovats, amb el mateix codi que el navegador, i executa aquestes. Qui fa una crida enviant uns `rawFormData` vàlids +al costat d'unes `extravars` diferents obté les extravars que corresponen als valors, no +les que ha enviat. + +De la petició, el servidor conserva `__verbose__` (només per als usuaris que tenen permès el mode detallat). Les +claus reservades (`__playbook__`, `__inventory__`, ...) surten del formulari, com sempre, i +`ansibleforms_user` és l'usuari que llança. + +### El que ha vist l'usuari no sempre és el que s'executa + +Construir les extravars vol dir tornar a avaluar el formulari: cada expressió i cada consulta s'executa +un altre cop al servidor, un moment després que ho hagi fet el navegador, com l'usuari que llança. Un valor +que depèn de **quan** o **on** s'avalua pot ser diferent, i en aquest cas es fa servir el +valor del servidor: + +| Què | Per què pot ser diferent | En quina mesura | +|---|---|---| +| `fn.fnTime()`, una marca de temps, un nom construït a partir de l'hora | s'avalua de nou, uns segons més tard | només importa en el límit d'un segon o d'una data. `fnTime` ja s'executa al servidor també en el flux del navegador, amb la mateixa zona horària (el `TZ` del contenidor) | +| una consulta, `fnRestAdvanced`, `fnSsh`, `fnDnsResolve`, la lectura d'un fitxer | les dades externes han canviat entremig | només quan han canviat | +| una expressió `runLocal` que fa servir `new Date()`, `toLocaleString`, `Intl` | el navegador fa servir la zona horària i l'idioma de l'usuari, el servidor els seus | només aquestes expressions | + +El mateix s'aplica a la **validació**: una regla que llegeix un camp d'aquests (`notIn` contra el resultat d'una +consulta, `validIf` sobre un indicador calculat) es comprova amb el valor del servidor. Els formularis les +extravars dels quals difereixen apareixen als avisos de `log` descrits més amunt; revisa'ls abans d'aplicar enforce. diff --git a/i18n/ca/_build_forms/launch-validation/passwords.md b/i18n/ca/_build_forms/launch-validation/passwords.md new file mode 100644 index 0000000..c36df14 --- /dev/null +++ b/i18n/ca/_build_forms/launch-validation/passwords.md @@ -0,0 +1,52 @@ +--- +layout: default +title: Contrasenyes +parent: Validació del llançament +nav_order: 5 +translated_from: 2fc2d2e8cdd997efaf221bd8e0114df2a4ee873e +--- + +# Contrasenyes +{: .no_toc } + +Com es validen, es desen i es mantenen fora de les API els camps de contrasenya +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +Un camp de contrasenya es valida com qualsevol altre camp. Ara bé, el seu valor es queda al servidor i no es retorna mai a +cap client. + +--- + +## On es desa una contrasenya + +El servidor desa la contrasenya amb la tasca, a les seves extravars: + +* Així, una **aprovació** pot continuar la tasca amb la contrasenya que ha introduït l'usuari. +* Un **rellançament tal com es va executar** la pot tornar a fer servir, quan la validació del llançament no és `enforce`. + +La contrasenya desada només es fa servir al servidor. + +--- + +## Què retornen les API + +Cap API no retorna mai una contrasenya: + +* Una tasca llegida a través de l'API REST o del `get_job` del servidor MCP emmascara tots els camps `password` del seu formulari, també dins de + les files de llista i dels subformularis YAML. +* `MASK_EXTRAVARS_REGEX` (per defecte `password|secret|token`) també emmascara totes les extravars el nom de les quals hi coincideix, per als + secrets que no són camps de contrasenya. + +--- + +## Què rep un rellançament + +Per emplenar per endavant un rellançament, el navegador rep les dades en brut del formulari de la tasca. Aquestes dades no contenen mai cap contrasenya, ni tan sols dins de +les files de llista o dels subformularis YAML, de manera que l'usuari torna a introduir la contrasenya. + +Un camp de contrasenya que les dependències del formulari amaguen no és necessari, i no s'ha de tornar a introduir. diff --git a/i18n/ca/_build_forms/launch-validation/relaunching.md b/i18n/ca/_build_forms/launch-validation/relaunching.md new file mode 100644 index 0000000..f2a1651 --- /dev/null +++ b/i18n/ca/_build_forms/launch-validation/relaunching.md @@ -0,0 +1,78 @@ +--- +layout: default +title: Rellançament +parent: Validació del llançament +nav_order: 6 +translated_from: 9f52ec39fd40e3d617d9537c5f7d356033bc9d49 +--- + +# Rellançament +{: .no_toc } + +Com es valida una tasca rellançada +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +Una tasca es pot rellançar de dues maneres. Com es comprova el rellançament depèn de quina es faci servir, i del mode de validació +del llançament. + +--- + +## Dos tipus de rellançament + +Els dos tipus es diferencien en si qui fa la crida envia valors nous o no: + +* **Tal com es va executar**: el botó Rellança, `POST /api/v2/job/{id}/relaunch` sense cos, o `relaunch_job` sense + `values`. +* **Amb canvis**: les mateixes crides amb valors nous, aplicats per sobre dels valors dels camps desats de la tasca: + +```bash +curl -X POST https://af.example.com/api/v2/job/42/relaunch \ + -H "Authorization: Bearer " -H "Content-Type: application/json" \ + -d '{ "values": { "vm_size": "large" } }' +``` + +--- + +## Com es comprova cadascun + +El mode de validació del llançament decideix si un rellançament es reprodueix o es torna a comprovar: + +| Rellançament | `off` / `log` | `enforce` | +|---|---|---| +| **Tal com es va executar** | reprodueix les extravars desades de la tasca, contrasenyes incloses | la comprovació completa, a partir dels valors dels camps desats | +| **Amb canvis** | la comprovació completa, sobre els valors desats amb els canvis aplicats a sobre | la comprovació completa, de la mateixa manera | + +Una excepció amb `enforce`: una tasca llançada per una programació de nivell d'administrador no té valors de camp propis, de manera que rellançar-la tal com es va executar +reprodueix les extravars desades de la programació, per a un administrador o per a un usuari amb l'opció de rol `allowScheduledJobs`. + +Un rellançament comprovat (vegeu [Registrar i aplicar](log-and-enforce.html)) inicia una tasca nova a nom de qui fa la crida. + +--- + +## Camps de contrasenya + +Els valors dels camps desats no contenen contrasenyes, de manera que un rellançament comprovat no en té cap per a un **camp de contrasenya visible**: + +* El rellançament es rebutja com a `unsupported`, amb els `passwordFields` que li falten. +* Torna a llançar el formulari i introdueix la contrasenya. +* Un camp de contrasenya que les dependències del formulari **amaguen** no és necessari i no bloqueja el rellançament. + +Amb `enforce`, això també s'aplica al botó Rellança. + +--- + +## Qui pot rellançar + +Tots dos tipus de rellançament requereixen: + +* que el formulari permeti el rellançament (`allowRelaunch`, true per defecte); +* l'opció de rol `allowJobRelaunch`; +* que l'usuari sigui **el propietari de la tasca**, un administrador o un usuari amb l'opció de rol `manageAllJobs`. + +Veure totes les tasques (`showAllJobLogs`) no és suficient per rellançar la tasca d'un altre usuari. Els aprovadors poden veure una tasca que espera la seva +aprovació, però tampoc no la poden rellançar. diff --git a/i18n/ca/_build_forms/launch-validation/rolling-it-out.md b/i18n/ca/_build_forms/launch-validation/rolling-it-out.md new file mode 100644 index 0000000..6c965d8 --- /dev/null +++ b/i18n/ca/_build_forms/launch-validation/rolling-it-out.md @@ -0,0 +1,61 @@ +--- +layout: default +title: Desplegar-la +parent: Validació del llançament +nav_order: 7 +translated_from: 399d39dbea694518926bcc20099d19438cbbac29 +--- + +# Desplegar-la +{: .no_toc } + +Passar una instància a enforce, i les limitacions conegudes +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +## Desplegament + +`enforce` és el valor per defecte. En una instància amb scripts o altres sistemes que llancen formularis per +REST, arriba-hi per passos, vigilant el registre abans de rebutjar res: + +1. Defineix `LAUNCH_VALIDATION=log` per a tota la instància (abans d'actualitzar, si es tracta d'una actualització). +2. Funciona en aquest mode durant un temps i revisa el registre: els avisos `would refuse` indiquen llançaments + que incompleixen les regles; els avisos `extravars differ` indiquen formularis que calculen alguna cosa + de manera diferent al servidor (una marca de temps, dades externes). Decideix per a cada formulari si això + importa. +3. Passa aquests formularis a `launchValidation: enforce`. Qui feia crides amb valors no vàlids o + amb extravars inventades ara rep un `422` amb el motiu. +4. Quan tots els formularis es comportin com s'espera, treu `LAUNCH_VALIDATION` (o posa-hi `enforce`) per a tota la instància. + +--- + +## Limitacions + +La validació del llançament encara no ho cobreix tot: + +- Els **formularis amb assistent** no es poden rellançar amb canvis, i una tasca d'assistent llançada abans de la 7.0 + no es pot rellançar amb `enforce` (no desava els valors dels passos). El servidor MCP + no pot llançar formularis amb assistent. +- La **resolució de marcadors** al navegador encara fa servir la seva pròpia còpia del codi del servidor; en + casos límit poc freqüents (`__undefined__`, cometes dins d'expressions) tots dos podrien resoldre un + marcador de manera diferent. `log` posa de manifest aquestes diferències. +- Les expressions **`runLocal`** s'executen al motor JavaScript del navegador quan és al navegador, i en un + entorn aïllat al servidor; el mateix codi produeix el mateix resultat, excepte quan depèn de + la zona horària o de l'idioma del navegador. + +--- + +## Formularis amb assistent + +Un [assistent](../forms/wizard.html) es comprova pas a pas: el navegador envia els valors de +cada pas, i el servidor comprova cada pas que l'usuari enviaria amb el seu propi subformulari. + +- Un pas es deixa fora quan és `optional` i l'usuari se l'ha saltat, o quan el seu `when` és fals. +- Un pas llegeix els passos anteriors a través de `$(__parent__..)`, amb els seus valors comprovats. +- Els errors indiquen el pas i el camp, com a `.`. +- Amb `enforce`, les extravars es construeixen al servidor, cada pas sota el seu `defaultModel`. +- Els camps de fitxer no s'admeten en un assistent. diff --git a/i18n/ca/_build_forms/launch-validation/switching-it-on.md b/i18n/ca/_build_forms/launch-validation/switching-it-on.md new file mode 100644 index 0000000..d139b5e --- /dev/null +++ b/i18n/ca/_build_forms/launch-validation/switching-it-on.md @@ -0,0 +1,71 @@ +--- +layout: default +title: Activar-la +parent: Validació del llançament +nav_order: 1 +translated_from: 2e5de5654a03389c7c8a7c05179e9dd79456b50b +--- + +# Activar-la +{: .no_toc } + +Per a tota la instància, o per a un formulari +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +La validació del llançament té dues opcions. **S'aplica la més estricta de les dues.** + +--- + +## Per a tota la instància: `LAUNCH_VALIDATION` + +La variable d'entorn [`LAUNCH_VALIDATION`](../customization/features.html#env_LAUNCH_VALIDATION) s'aplica a tots els formularis: + +- `off`: cap comprovació al servidor; la tasca s'executa amb les extravars que ha enviat el navegador o qui fa la crida. +- `log`: es comprova cada llançament; el que es rebutjaria s'escriu al registre com a + avís, i el llançament s'executa igual que abans. +- `enforce` (per defecte): un llançament no vàlid es rebutja, i un de vàlid s'executa amb les extravars que + construeix el servidor. + +Un valor buit o desconegut també equival a `enforce`. Els canvis tenen efecte sense reiniciar. + +{: .warning } +> **L'actualització canvia el comportament.** Una instància que no defineix `LAUNCH_VALIDATION` aplica la validació a +> tots els llançaments després de l'actualització. Els scripts que criden `POST /api/v2/job` sense `rawFormData`, +> o amb valors que incompleixen les regles d'un formulari, es rebutgen amb un `422`. Defineix +> `LAUNCH_VALIDATION=log` abans d'actualitzar per veure què es rebutjaria, o `off` per mantenir el +> comportament antic (vegeu [Desplegar-la](rolling-it-out.html)). + +--- + +## Per a un formulari: `launchValidation` + +Un formulari pot definir el seu propi nivell: + +```yaml +- name: Create VM + type: ansible + roles: + - default + playbook: vm.yml + launchValidation: enforce # off | log | enforce + fields: + - name: vm_name + type: text + required: true +``` + +Fes servir aquesta opció en una instància que funciona amb `off` o `log`, per a un formulari que saps que es +llançarà per REST: aquest formulari queda en enforce, mentre que la resta de la instància no. També es pot definir al dissenyador, a la +configuració del formulari. + +**Un formulari es pot fer més estricte que la instància, mai més permissiu.** Amb `LAUNCH_VALIDATION` +a `enforce`, el `launchValidation: off` d'un formulari no té cap efecte: un formulari no pot passar per sobre +de la decisió d'un operador. + +Els formularis amb assistent també la fan servir: el llançament d'un assistent es comprova pas a pas, cada pas amb el seu propi +subformulari (vegeu [Formularis amb assistent](rolling-it-out.html#wizard-forms)). diff --git a/i18n/ca/_build_forms/workflows/designer.md b/i18n/ca/_build_forms/workflows/designer.md new file mode 100644 index 0000000..2003dfe --- /dev/null +++ b/i18n/ca/_build_forms/workflows/designer.md @@ -0,0 +1,107 @@ +--- +layout: default +title: Edició al dissenyador +parent: Workflows +nav_order: 2 +translated_from: dd4e281ec223f5c4995d804e774ac49e4d5934da +--- + +# Edició al dissenyador +{: .no_toc } + +Dibuixa un workflow i prova'l sense executar res +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +## La secció Fluxos de treball + +**Dissenyador > Fluxos de treball** mostra els fitxers de workflow en un explorador de fitxers, amb les pestanyes YAML, Visual i Previsualització de totes les +seccions del [dissenyador](../designer/). + +- **El botó `+`** de la barra d'eines crea un fitxer de workflow, amb un workflow buit per començar. +- **YAML** mostra el fitxer tal com està escrit. Les altres pestanyes també conserven els comentaris i l'ordre de les claus. +- **Visual** dibuixa cada workflow del fitxer com un graf, amb el seu nom i la seva descripció a sobre. Un fitxer amb dos workflows + mostra tots dos, l'un sota l'altre. +- **Previsualització** és una simulació del workflow: vegeu [Provar-lo](#trying-it-out). + +Els problemes es mostren a sobre del graf, cadascun amb un enllaç que obre el YAML a la seva línia: un enllaç a un node que no +existeix, un bucle, o un playbook, inventari, credencial, runner o repositori que el dissenyador no coneix. + +--- + +## El graf + +El graf es llegeix d'esquerra a dreta, des de **START** fins als últims nodes. Cada node mostra el seu identificador i, a sota, què +executa; els enllaços tenen colors segons què els activa, tal com indica la llegenda dins del graf: en cas d'èxit, en cas d'error, +sempre. + +- **Fes clic a START** per afegir un primer node: un node sense pare, que s'executa tan bon punt comença el workflow. +- **Fes clic en un node** per editar-lo. +- **Fes clic en un enllaç** per canviar què l'activa, o per treure'l. + +--- + +## Afegir un node + +Un node nou s'afegeix amb un assistent: **Node nou si té èxit**, **Node nou si falla** o **Node nou sempre** en un node +existent, o START per al primer. + +1. **Què executa**: l'identificador del node, **Executa** (quin tipus de node és i, per a un node de playbook, on s'executa) + i què executa: un playbook o una plantilla o job, un workflow, el nom i el temps límit d'una aprovació, o un repositori. Vegeu + [On s'executa un node](#where-a-node-runs). +2. **Com s'executa**: les opcions d'execució: l'inventari, les credencials, el límit, les etiquetes, la verbositat, + el mode check i el mode diff, la condició (**S'executa si**) i **Valors de** (vegeu [el fitxer de workflow](file.html#run-settings)). +3. **On va**: el node després del qual s'executa, i en quin cas. + +**Crear** afegeix el node al YAML. + +--- + +## On s'executa un node + +**Executa** indica què executa un node i on, en una sola llista: **Playbook a l'RTE**, **Plantilla a AWX**, **Plantilla a +Semaphore**, **Job a Rundeck**, **Job a Jenkins**, i després **Workflow**, **Aprovació** i **Pull de repositori**. + +| Executa | El camp de sota | Runner | +|---|---|---| +| **Playbook a l'RTE** | **Playbook**: un playbook del dissenyador | **L'RTE per defecte**, o un runner RTE pel nom | +| **Plantilla a AWX** (AAP i Ascender inclosos) | **Plantilla**: el nom de la plantilla, escrit a mà | els runners d'AWX, cadascun amb la seva variant | +| **Plantilla a Semaphore** | **Plantilla**: el nom de la plantilla, escrit a mà | els runners de Semaphore | +| **Job a Rundeck** o **Job a Jenkins** | **Job**: el nom del job, escrit a mà | els runners de Rundeck o de Jenkins | + +- **Playbook a l'RTE** s'ofereix sempre; els altres, només quan la instància té un [runner](../runners.html) d'aquest tipus. +- **Runner** només mostra els runners d'aquest tipus, amb el per defecte marcat i preseleccionat (o el primer per nom). +- Triar un altre lloc esborra el que executa el node, de manera que s'ha de tornar a triar. +- Un node el runner del qual el dissenyador no coneix mostra **Plantilla o job a** aquest runner. + +El fitxer de workflow no canvia: un node així és un node `job_template` amb un `runner:` (vegeu +[el fitxer de workflow](file.html#run-settings)). + +--- + +## Editar un node + +En fer clic en un node s'obre el seu diàleg, amb quatre pestanyes: + +| Pestanya | Què conté | +|---|---| +| **Què executa** | L'identificador, **Executa**, què executa i, per a un node de playbook, el runner | +| **Com s'executa** | Les opcions d'execució; les credencials es trien d'una llista, i cadascuna s'afegeix amb `+` | +| **S'executa després de** | Els enllaços que arriben al node, i **Tots els pares han de convergir** | +| **Executa després** | Els enllaços que en surten, amb **Enllaçar a un node existent:** i **Enllaçar a un node nou:** | + +**Mostra en YAML** obre el YAML al node, i **Treure node** el treu amb els seus enllaços. Cada canvi s'escriu al +YAML immediatament; **Desa** desa el fitxer. + +--- + +## Provar-lo + +La pestanya **Previsualització** recorre el workflow sense llançar res, segons les regles d'AWX. + +Tots els nodes comencen amb èxit. Fes clic en un node perquè falli, i torna-hi a fer clic perquè tingui èxit; llavors el graf mostra +quins nodes s'executarien, quins no s'executarien i si el workflow fallaria. **Restablir** torna a fer que tots els nodes tinguin èxit. diff --git a/i18n/ca/_build_forms/workflows/file.md b/i18n/ca/_build_forms/workflows/file.md new file mode 100644 index 0000000..8918c03 --- /dev/null +++ b/i18n/ca/_build_forms/workflows/file.md @@ -0,0 +1,165 @@ +--- +layout: default +title: El fitxer de workflow +parent: Workflows +nav_order: 1 +translated_from: bb4d3027e33a5bfd11443369b621eb34c4af2f68 +--- + +# El fitxer de workflow +{: .no_toc } + +La sintaxi del workflow, els tipus de node i les opcions d'execució de cada node +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +## On són els fitxers de workflow + +Els fitxers de workflow són fitxers YAML a la carpeta local de workflows i a cada repositori que es fa servir per a workflows. + +- **La carpeta local** és [`WORKFLOWS_PATH`](../customization/paths.html#env_WORKFLOWS_PATH), per defecte `workflows` dins de la + carpeta persistent. +- **Un repositori** amb **Fer servir per a workflows?** activat es llegeix sencer, de manera que els seus fitxers de workflow poden estar a qualsevol carpeta. El + dissenyador els torna a desar al repositori, i **Push** els envia al remot. + +Es llegeix cada fitxer YAML que conté `workflow_job_templates`, fins a sis carpetes de profunditat, i un fitxer pot contenir diversos +workflows. Un formulari anomena un workflow pel seu `name`, així que mantén els noms únics: quan dos workflows comparteixen nom, una tasca que +l'executa falla i demana que en reanomenis un. + +--- + +## La sintaxi + +Un fitxer de workflow s'escriu amb la sintaxi d'una exportació d'AWX, amb els nodes a `related.workflow_nodes`: + +```yaml +workflow_job_templates: + - name: deploy-app + description: Builds, approves and deploys the application + extra_vars: + app_name: orders-api + related: + workflow_nodes: + - identifier: build + unified_job_template: + name: build.yaml + type: job_template + inventory: + name: staging + related: + credentials: + - name: deploy-ssh + success_nodes: + - identifier: approve + failure_nodes: + - identifier: notify + - identifier: approve + unified_job_template: + name: Approve the deploy + type: workflow_approval_template + timeout: 3600 + related: + success_nodes: + - identifier: deploy + - identifier: deploy + unified_job_template: + name: deploy.yaml + type: job_template + inventory: + name: production + limit: web + job_tags: deploy + - identifier: notify + unified_job_template: + name: notify.yaml + type: job_template +``` + +També es llegeix la forma de la col·lecció `awx.awx`: `workflow_nodes` directament sota el workflow, i noms escrits com a +cadenes simples (`inventory: staging`) en lloc de mapes (`inventory: {name: staging}`). + +### El workflow + +Una entrada de workflow té unes quantes claus pròpies, al costat dels seus nodes: + +| Clau | Què és | +|---|---| +| `name` | El nom del workflow, el que indica el `workflow:` d'un formulari | +| `description` | Per a què serveix, es mostra al dissenyador | +| `extra_vars` | Variables que rep cada node; els valors del formulari hi tenen prioritat | +| `related.workflow_nodes` | Els nodes | + +### Un node + +Cada node té un identificador, el que executa i els seus enllaços: + +| Clau | Què és | +|---|---| +| `identifier` | L'id del node: lletres, dígits, punts, guions, dos punts i guions baixos, únic dins del workflow | +| `unified_job_template.type` | Què executa el node: vegeu [tipus de node](#node-types) | +| `unified_job_template.name` | El playbook, el workflow, l'aprovació o el repositori que executa | +| `related.success_nodes` | Els nodes que s'executen quan aquest té èxit | +| `related.failure_nodes` | Els nodes que s'executen quan aquest falla | +| `related.always_nodes` | Els nodes que s'executen quan aquest ha acabat, sigui com sigui | +| `all_parents_must_converge` | `true`: el node espera que s'activin tots els enllaços que hi arriben, no només un | + +Els enllaços han d'anar endavant: un workflow els enllaços del qual fan un bucle no s'executa. + +--- + +## Tipus de node + +Un node executa una de quatre coses, anomenades com les anomena AWX: + +| Tipus | Què executa el node | +|---|---| +| `job_template` | Un dels playbooks del dissenyador, com a tasca pròpia a l'RTE; o, amb `runner:`, la plantilla o el job d'aquest runner | +| `workflow_job_template` | Un altre workflow, com a tasca de workflow filla; els workflows es poden niar fins a cinc nivells | +| `workflow_approval_template` | Una aprovació: la tasca del workflow espera fins que algú l'aprova o la rebutja | +| `project` | Un pull del repositori que indica (l'actualització de projecte d'AWX) | + +El `unified_job_template.timeout` d'un node d'aprovació s'expressa en segons. Quan passa sense resposta, el node falla; amb `0` o sense +temps límit, espera una resposta el temps que calgui. Una aprovació rebutjada fa fallar el node, i el workflow continua pels seus +enllaços. + +--- + +## Opcions d'execució + +Un node `job_template` admet les opcions d'un node d'AWX, al mateix node: + +| Clau | Què fa | +|---|---| +| `inventory` | L'inventari contra el qual s'executa el playbook, pel seu nom, com l'`inventory:` d'un formulari | +| `related.credentials` | Les credencials: cadascuna arriba al playbook amb el seu propi nom, i la primera de tipus *SSH* també és l'accés amb què es connecta ansible. Una de tipus vault només obre els vaults | +| `limit` | Només s'executa en aquests hosts (`--limit`) | +| `job_tags` | Només executa les tasques amb aquestes etiquetes (`--tags`) | +| `skip_tags` | Omet les tasques amb aquestes etiquetes (`--skip-tags`) | +| `verbosity` | De `0` a `5`: el nombre de `-v` | +| `diff_mode` | `true`: mostra els canvis (`--diff`) | +| `job_type` | `check`: una simulació (`--check`); `run` o res: una execució real | +| `extra_data` | Variables que rep aquest node, per sota de les `extra_vars` del workflow i dels valors del formulari | + +La tasca del node rep els valors del formulari com a extra vars. Els valors del formulari tenen prioritat sobre les `extra_vars` del workflow, que tenen prioritat +sobre l'`extra_data` del node, com passa amb les respostes d'un survey a AWX. + +--- + +## Claus pròpies d'AnsibleForms + +Tres claus d'un node són pròpies d'AnsibleForms, i AWX les ignora, de manera que un workflow pot fer el que fa un formulari multipas: + +| Clau | Què fa | +|---|---| +| `runner` | En un node `job_template`, executa la plantilla o el job d'aquest runner en lloc d'un playbook del dissenyador: AWX, AAP, Ascender, Semaphore, Rundeck o Jenkins. Un runner RTE hi executa el playbook del node. Un mateix workflow els pot combinar. | +| `if_extra_var` | El node només s'executa quan aquesta extra var és `true`, com l'`ifExtraVar` d'un pas multistep. Si no es compleix, el node s'omet, i el que el segueix s'executa com després d'un èxit. No en un node d'aprovació, que sempre s'executa. | +| `extra_vars_key` | El node només rep aquesta clau de les extra vars, amb l'usuari copiat a dins, com la `key` d'un pas multistep | + +En un runner de plantilles, `unified_job_template.name` és la plantilla o el job que cal executar, i el `limit`, els `job_tags`, el mode check +i el mode diff del node es passen tal com els passaria un formulari del tipus d'aquest runner. Una `verbosity` superior a `0` activa el +`verbose` del formulari, i `skip_tags` no es passa. Només un runner d'AWX (AWX, AAP o Ascender) rep l'inventari del node, i les +credencials com a credencials d'AWX; Semaphore, Rundeck i Jenkins reben les credencials com els `credentials` d'un formulari. diff --git a/i18n/ca/_build_forms/workflows/index.md b/i18n/ca/_build_forms/workflows/index.md new file mode 100644 index 0000000..acbaf0f --- /dev/null +++ b/i18n/ca/_build_forms/workflows/index.md @@ -0,0 +1,99 @@ +--- +layout: default +title: Workflows +nav_order: 5 +has_children: true +has_toc: false +permalink: /workflows/ +translated_from: e6133a683d5bc1d0ba822dd52b4fed99028ea63c +--- + +# Workflows +{: .no_toc } + +Encadena playbooks, aprovacions i altres workflows, com fa AWX +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +Per als autors de formularis: què és un workflow, com s'executen els seus nodes i on continuar llegint. + +Un workflow és un graf de nodes. Cada node executa alguna cosa: un dels playbooks del dissenyador, un altre workflow, una aprovació +o un pull d'un repositori. Els enllaços entre els nodes indiquen què s'executa després: si té èxit, si falla o sempre. Un formulari de +[tipus `workflow`](../forms/workflow.html) el llança, i la pàgina de tasques el dibuixa en directe mentre s'executa. + +Els workflows segueixen la sintaxi i les regles d'AWX, de manera que un workflow exportat d'AWX es llegeix igual a AnsibleForms. S'executen a +l'RTE, sense AWX: un node de playbook és una tasca pròpia, amb l'inventari, les credencials, el límit i les etiquetes del node. + +--- + +## Com s'executa un workflow + +Els nodes s'executen segons les regles d'AWX, i les branques que no depenen l'una de l'altra s'executen en paral·lel. + +- **Un node sense pare comença de seguida**, quan comença el workflow. +- **Un enllaç s'activa quan el seu node ha acabat**: un enllaç *si té èxit* després d'un èxit, un enllaç *si falla* després d'una fallada, + un enllaç *sempre* després de qualsevol dels dos. Un node cancel·lat no activa cap dels seus enllaços. +- **Un node comença tan bon punt s'activa un dels enllaços que hi arriben.** Amb **Tots els pares han de convergir** activat, espera fins que s'han activat tots + els enllaços que hi arriben. +- **Un node que ja no pot començar es marca com a *no s'executa***, igual que els nodes que només ell podia iniciar. +- **El workflow falla quan un node ha fallat i res no ho gestiona**: aquest node no té cap enllaç *si falla* ni cap enllaç *sempre*. + Una fallada que gestiona un enllaç no fa fallar el workflow. + +Un node amb una condició (`if_extra_var`) que no es compleix s'omet. El que el segueix s'executa com després d'un èxit. Un node +d'aprovació no admet condició: sempre espera una resposta. + +--- + +## Passar dades entre nodes + +El que el playbook d'un node recull amb `set_stats` arriba als nodes posteriors com a extra vars, de la mateixa manera que AWX passa els +artefactes d'una tasca. Un node rep les dades de tots els pares l'enllaç dels quals cap a ell s'ha activat, fusionades en l'ordre en què estan +escrits els pares, i passa endavant el que ha rebut més les dades de la seva pròpia tasca; si tots dos defineixen una clau, guanya la seva. + +```yaml +# build.yaml, the first node : its version and build id go to the nodes after it +- name: Build + hosts: localhost + gather_facts: false + tasks: + - name: Pass the build on + ansible.builtin.set_stats: + data: + version: "2.4.1" + build_id: 42 +``` + +Un node posterior llegeix llavors {% raw %}`{{ version }}` i `{{ build_id }}`{% endraw %} com qualsevol altra extra var. + +Les extra vars d'un node provenen de quatre llocs. Un d'ells, `extra_data`, són les variables pròpies del node: el nom que els dona AWX, +definides al node al [fitxer de workflow](file.html#run-settings). Quan dos llocs defineixen la mateixa clau, l'ordre de precedència és +el d'AWX, de menor a major: + +| Origen | Guanya a | +|---|---| +| les variables pròpies del node (`extra_data`) | res | +| les dades passades amb `set_stats` | l'`extra_data` del node | +| les `extra_vars` del workflow | les dades passades | +| els valors del formulari | tot | + +- Només es passen les dades de tot el playbook: `set_stats` amb `per_host: false`, el seu valor per defecte. +- Un node d'aprovació, un node omès i un node de projecte passen endavant el que els ha arribat. +- La sortida d'un node acaba amb les claus que ha passat endavant, només pel nom, ja que els seus valors poden ser secrets. +- La tasca del node conserva les seves dades com a artefactes (**Mostra els artefactes** a la seva pàgina), i la tasca del workflow conserva les dades de tots + els seus nodes, de manera que un workflow niat també les passa als nodes posteriors. +- Un node que s'executa en un runner d'AWX passa endavant els artefactes de la seva tasca d'AWX de la mateixa manera. +--- + +## En aquesta secció + +Les pàgines següents descriuen els workflows en detall: + +| Pàgina | Què tracta | +|---|---| +| [El fitxer de workflow](file.html) | La sintaxi del fitxer, els tipus de node i les opcions d'execució de cada node | +| [Edició al dissenyador](designer.html) | La secció Fluxos de treball del dissenyador: el graf, els diàlegs de node i d'enllaç i la simulació | +| [Executar un workflow](running.html) | El formulari que el llança, la pàgina de la tasca, les sortides dels nodes, les aprovacions i l'avortament | diff --git a/i18n/ca/_build_forms/workflows/running.md b/i18n/ca/_build_forms/workflows/running.md new file mode 100644 index 0000000..33a4a57 --- /dev/null +++ b/i18n/ca/_build_forms/workflows/running.md @@ -0,0 +1,103 @@ +--- +layout: default +title: Executar un workflow +parent: Workflows +nav_order: 3 +translated_from: 1883c268cde716170bdb84c7f2df49e9122dc55d +--- + +# Executar un workflow +{: .no_toc } + +Llança un workflow des d'un formulari i segueix-lo a la pàgina de tasques +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +## El formulari + +Un formulari de [tipus `workflow`](../forms/workflow.html) llança un workflow, indicat amb `workflow:` com es fa amb un playbook: pel +seu **fitxer** a la carpeta de workflows, amb les seves subcarpetes (`team/deploy-app.yml`), o pel **nom** del workflow dins +del fitxer (`deploy-app`): + +```yaml +- name: Deploy the app + type: workflow + workflow: team/deploy-app.yml + roles: + - admin + fields: + - name: app_name + type: text + default: orders-api +``` + +Els camps del formulari arriben a cada node com a extra vars, i també les seves [`credentials`](../forms/workflow.html#workflow_credentials), amb els noms +que els dona el formulari, igual que els d'un formulari multipas arriben als seus passos: + +```yaml +- name: Provision NAS storage + type: workflow + workflow: nas.yml + credentials: + ontap: ontap_automation # every node's playbook gets `ontap` +``` + +Les credencials pròpies d'un node, definides al fitxer de workflow, arriben al seu playbook amb el seu propi nom i guanyen si tots dos fan servir el mateix nom. A la pestanya Visual d'un formulari al dissenyador, **Workflow** és una llista dels +fitxers de workflow del dissenyador. + +Un nom de fitxer sol també es troba en una subcarpeta, quan només un fitxer el té. Dos workflows amb el mateix nom aturen un formulari que +l'indica pel nom, i el dissenyador avisa quan deses el segon: reanomena'n un, o indica'n el fitxer. Un workflow que no es pot +trobar fa que la tasca acabi fallida, amb el motiu a la sortida. + +--- + +## La tasca + +Una tasca de workflow s'executa al servidor d'AnsibleForms, i cada node de playbook s'executa com una tasca pròpia, filla de la tasca del +workflow, igual que els passos d'un formulari multipas: un playbook del dissenyador a l'RTE o, per a un node amb un `runner:`, la plantilla +o el job d'aquest runner a AWX, AAP, Ascender, Semaphore, Rundeck o Jenkins (vegeu [On s'executa un node](designer.html#where-a-node-runs)). + +La pàgina de la tasca dibuixa el workflow en directe: cada node amb el color del seu estat, els enllaços que s'han activat i els nodes que no +s'executaran. Les dades de la part superior indiquen el workflow en lloc d'un playbook. + +- **Fes clic en un node** que hagi acabat per obrir-ne la sortida en un diàleg. +- **La sortida** conté la sortida de cada node sota una capçalera `WORKFLOW NODE [identifier] (status)`, en l'ordre en què han + acabat els nodes. +- **Mostra les extravars** i **Mostra els artefactes**, a la capçalera de cada node a la sortida i al diàleg que s'obre des del graf, + mostren les extravars i els artefactes propis d'aquest node (`{}` si no en té), en JSON o YAML, amb un botó Copia. + +Les extravars d'un node contenen el que li han passat els nodes anteriors, i els seus artefactes, el que el seu playbook ha recollit amb +`set_stats`. Els dos botons segueixen les [opcions de rol](../config/roles.html#role-options) `showExtravars` i +`showArtifacts`. Les mateixes dades s'obtenen de `GET /api/v2/job/{id}/node/{nodeId}`, per a qualsevol que pugui veure la tasca. + +La tasca falla quan un node ha fallat i res no ho ha gestionat, segons la regla d'AWX; si no, té èxit. + +--- + +## Aprovacions + +Un node d'aprovació reté la tasca del workflow fins que algú hi respon. + +Quan el workflow arriba a un node d'aprovació, l'estat de la tasca passa a **Esperant aprovació**: es mostra a la campaneta i a la +pàgina de la tasca, com un [punt d'aprovació](../forms/approval.html) d'un formulari. El nom del node és el títol de l'aprovació, i la seva descripció, +el missatge; la resta surt de l'`approval` del formulari: + +- els seus `roles` decideixen qui la pot aprovar o rebutjar, i `allowSelf`, si qui l'ha llançada també la pot aprovar; +- la sol·licitud s'envia a les seves `notifications` i `channels`. + +Un formulari de workflow sense `approval` també reté la tasca en un node d'aprovació, però llavors només un administrador la pot aprovar. + +- **Aprovada**: el node té èxit i el workflow continua pels seus enllaços *si té èxit*. +- **Rebutjada**: el node falla i el workflow continua pels seus enllaços *si falla*. +- **Temps esgotat**: passat el temps límit del node sense resposta, el node també falla. + +--- + +## Avortar + +**Avorta** en una tasca de workflow en execució l'atura: les tasques dels nodes en curs s'avorten, no comença res més, i l'aprovació que +estigui esperant es cancel·la. Una tasca de workflow que espera una aprovació també es pot avortar. diff --git a/i18n/ca/_configure/announcements.md b/i18n/ca/_configure/announcements.md new file mode 100644 index 0000000..32e3057 --- /dev/null +++ b/i18n/ca/_configure/announcements.md @@ -0,0 +1,48 @@ +--- +layout: default +title: Anuncis +nav_order: 1 +has_children: true +has_toc: false +permalink: /announcements.html +translated_from: 9569cbdaa1c1d1d215f521f21023566e3a4df572 +--- + +# Anuncis +{: .no_toc } + +Missatges sota la capçalera per a tothom, com ara una finestra de manteniment, cadascun des del seu inici fins al seu final +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +Per a administradors: avisa tots els usuaris d'una finestra de manteniment o d'una incidència, a **Configuració > Aparença > Anuncis**. + +La pàgina necessita l'opció de rol `showSettings` o `showAppearanceSettings`. Des de la 7.3.0 és una sola llista, i cada anunci +té la seva pròpia pàgina i el seu interruptor Activat. + +--- + +## En aquesta secció + +| Pàgina | Què hi trobaràs | +|---|---| +| [General](announcements/general.html) | L'interruptor Activat de cada anunci, que va substituir l'interruptor de tots alhora | +| [Llista](announcements/list.html) | Els anuncis que no han acabat, les seves columnes i la pàgina d'un anunci | +| [Afegir-ne un](announcements/adding-one.html) | L'assistent de dos passos: el missatge i, després, quan es mostra | + + +--- + +## On es mostren + +Els anuncis es mostren com una línia sota la capçalera de cada pàgina, per a tots els usuaris que han iniciat sessió, cadascun amb el color del seu tipus. + +Se'n poden mostrar diversos d'activats alhora, el més recent primer. La pàgina d'inici de sessió i un formulari incrustat en un altre lloc web no en mostren cap. + +Cadascun té un botó per tancar-lo. Un anunci tancat continua tancat en aquella pestanya del navegador fins que es tanca la pestanya, o +fins que canvia el seu missatge o la seva data de final. Un anunci desat arriba alhora a tots els navegadors oberts; un que +arriba a la seva data d'inici o de final s'hi mostra o s'hi amaga en menys d'un minut. diff --git a/i18n/ca/_configure/announcements/adding-one.md b/i18n/ca/_configure/announcements/adding-one.md new file mode 100644 index 0000000..e5231e4 --- /dev/null +++ b/i18n/ca/_configure/announcements/adding-one.md @@ -0,0 +1,29 @@ +--- +layout: default +title: Afegir-ne un +parent: Anuncis +nav_order: 3 +translated_from: 0391ac4a8ba2f25d94a030831cc1a421d70ea0ba +--- + +# Afegir-ne un +{: .no_toc } + +L'assistent de dos passos: el missatge i, després, quan es mostra +{: .fs-6 .fw-300 } + +**Afegeix anunci** obre un assistent de dos passos. **Missatge** pregunta què diu: + +| Camp | Significat | +|---|---| +| **Missatge** | El text, com a màxim 500 caràcters. Obligatori. | +| **Tipus** | El seu color i la seva icona: blau per a Informació (el predeterminat), ambre per a Advertència, vermell per a Perill | + +**Quan** pregunta quan es mostra: + +| Camp | Significat | +|---|---| +| **Data d'inici** | Es mostra a partir d'aquest moment. Deixa-la buida per mostrar-lo de seguida. | +| **Data de final** | En aquest moment s'amaga i se suprimeix. Deixa-la buida per conservar-lo fins que el suprimeixis. | + +La data de final ha de ser posterior a la data d'inici i ha de ser en el futur. diff --git a/i18n/ca/_configure/announcements/general.md b/i18n/ca/_configure/announcements/general.md new file mode 100644 index 0000000..3b4693d --- /dev/null +++ b/i18n/ca/_configure/announcements/general.md @@ -0,0 +1,33 @@ +--- +layout: default +title: General +parent: Anuncis +nav_order: 1 +translated_from: e5c14d608eacfef0f3aa1a322d0ac0275b55f91e +--- + +# General +{: .no_toc } + +L'interruptor Activat de cada anunci, que va substituir l'interruptor de tots alhora +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +## Activar o desactivar un anunci + +Des de la 7.3.0, cada anunci s'activa o es desactiva per separat, amb el seu interruptor **Activat**. + +Un anunci nou està activat. **Desactiva** al menú de la seva fila, o l'interruptor **Activat** de la seva pàgina, l'amaga de sota la capçalera i el conserva +a la llista, i **Activa** el torna a mostrar des de la seva data d'inici fins a la seva data de final. L'interruptor es desa a l'instant. + +--- + +## L'interruptor Mostra els anuncis de la 7.2 + +Fins a la 7.2, una pestanya **General** tenia un interruptor **Mostra els anuncis** que els activava o desactivava tots alhora. + +Des de la 7.3.0 aquest interruptor ja no hi és. Si estava desactivat, l'actualització desactiva tots els anuncis, perquè cap no comenci a mostrar-se: torna a activar els que vulguis. diff --git a/i18n/ca/_configure/announcements/list.md b/i18n/ca/_configure/announcements/list.md new file mode 100644 index 0000000..61dd02d --- /dev/null +++ b/i18n/ca/_configure/announcements/list.md @@ -0,0 +1,44 @@ +--- +layout: default +title: Llista +parent: Anuncis +nav_order: 2 +translated_from: 3bbe4ccb28f9305a450ac85b7d99531ce28a84cd +--- + +# Llista +{: .no_toc } + +Els anuncis que no han acabat, les seves columnes i la pàgina d'un anunci +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +## La llista + +**Configuració > Aparença > Anuncis** llista tots els anuncis que no han acabat, amb aquestes columnes: + +| Columna | Significat | +|---|---| +| **Activat** | Si es mostra sota la capçalera des del seu inici fins al seu final (des de la 7.3.0) | +| **Missatge** | El text sota la capçalera | +| **Tipus** | Informació, Advertència o Perill | +| **Data d'inici** | Quan comença a mostrar-se; `–` quan es mostra de seguida | +| **Data de final** | Quan acaba; `–` quan es mostra fins que se suprimeix | +| **Creat per** | Qui l'ha afegit | + +Un clic en una fila, o **Edita** al menú de la seva fila, obre la pàgina de l'anunci. El menú també té **Activa** o **Desactiva**, i **Suprimeix**. + +Quan passa la seva data de final, l'anunci se suprimeix: la llista només conserva els que han de venir i els que s'estan mostrant. + +--- + +## La pàgina d'un anunci + +Des de la 7.3.0, cada anunci s'obre a la seva pròpia pàgina, a `/settings/announcements/`, amb una pestanya, **Detalls**. + +Conté el missatge, el tipus, les dates d'inici i de final i l'interruptor **Activat**, que es desa a l'instant; els altres camps es desen +amb **Desa**, i **Suprimeix** elimina l'anunci. El títol de la pàgina l'anomena pels primers caràcters del seu missatge. diff --git a/i18n/ca/_configure/appearance.md b/i18n/ca/_configure/appearance.md new file mode 100644 index 0000000..43034d3 --- /dev/null +++ b/i18n/ca/_configure/appearance.md @@ -0,0 +1,41 @@ +--- +layout: default +title: Aparença +nav_order: 2 +has_children: true +has_toc: false +permalink: /appearance.html +translated_from: 8dacce30ad7f7530858b04514b1edbbf19ea73d2 +--- + +# Aparença +{: .no_toc } + +Els valors predeterminats, el nom, el logotip, la icona del navegador, els enllaços de la capçalera i les etiquetes al costat del logotip +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +Per a administradors: dona a la instància el teu propi aspecte, a **Configuració > Aparença**, amb l'opció de rol `showSettings`. +L'opció de rol `showAppearanceSettings` tota sola també obre aquestes pàgines, anuncis inclosos, sense la resta de la configuració. + +Les pàgines d'aquest grup són **Valors predeterminats**, **Nom**, **Logotip**, **Icona**, **Enllaços**, **Etiquetes** i **Anuncis**; +els anuncis tenen una pàgina pròpia, [Anuncis](announcements.html). Un valor predeterminat, un nom, un enllaç o una etiqueta que es desa +es mostra a l'instant a tots els navegadors oberts. + +--- + +## En aquesta secció + +| Pàgina | Què hi trobaràs | +|---|---| +| [Valors predeterminats](appearance/defaults.html) | El tema, l'idioma, la zona horària i el format de data per als usuaris que no n'han triat cap | +| [Nom](appearance/name.html) | El nom de l'aplicació a la pestanya del navegador i a la pàgina d'inici de sessió | +| [Logotip](appearance/logo.html) | El teu propi logotip a la capçalera | +| [Icona](appearance/icon.html) | La teva pròpia icona a la pestanya del navegador i a les adreces d'interès | +| [Enllaços](appearance/links.html) | Els enllaços de la capçalera, els integrats i els teus | +| [Etiquetes](appearance/labels.html) | Etiquetes al costat del logotip que indiquen quina instància és aquesta; una sola etiqueta Environment fins a la 7.2 | + diff --git a/i18n/ca/_configure/appearance/defaults.md b/i18n/ca/_configure/appearance/defaults.md new file mode 100644 index 0000000..31db607 --- /dev/null +++ b/i18n/ca/_configure/appearance/defaults.md @@ -0,0 +1,46 @@ +--- +layout: default +title: Valors predeterminats +parent: Aparença +nav_order: 1 +translated_from: 2974af3a3fc29115349fad94498cac9ecd8c6123 +--- + +# Valors predeterminats +{: .no_toc } + +El tema, l'idioma, la zona horària i el format de data per als usuaris que no n'han triat cap +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +## Els valors predeterminats + +**Valors predeterminats** defineix com es veu l'aplicació per a un usuari que no ha fet cap tria pròpia a les seves +[preferències](../profile/preferences.html); la tria del mateix usuari sempre té prioritat: + +| Camp | Opcions | Sense tria | +|---|---|---| +| **Tema predeterminat** | Segueix el navegador, Clar, Fosc o Color, amb un de 12 colors per a Color | Segueix el navegador (Clar fins a la 7.2) | +| **Idioma predeterminat** | Els idiomes de l'aplicació, desat a [`DEFAULT_LANGUAGE`](../customization/server.html#env_DEFAULT_LANGUAGE) | Anglès | +| **Vista de formularis predeterminada** | Mosaics o Llista, per a la pàgina de formularis | Mosaics | +| **Zona horària predeterminada** | UTC, la del navegador de cada usuari o qualsevol zona pel seu nom | UTC | +| **Format de data predeterminat** | `YYYY-MM-DD`, `DD/MM/YYYY`, `MM/DD/YYYY` o `DD.MM.YYYY`, mostrat amb la data d'avui | `YYYY-MM-DD` | + +L'idioma és una variable d'entorn i s'aplica sense reiniciar. Amb +[`ALLOW_ENV_EDIT`](../customization/configuration.html#env_ALLOW_ENV_EDIT) a `0`, la pàgina el mostra només de lectura. + +Des de la 7.3.0 la pàgina és a les dues pestanyes de les preferències del perfil, **Aparença** (tema, idioma i vista de formularis) i **Data i +hora** (zona horària i format de data, amb una previsualització de l'hora actual), i el seu quadre de cerca llista les coincidències sota el nom de cada pestanya. + +--- + +## Seguir el navegador + +Des de la 7.3.0 **Segueix el navegador** mostra a cada usuari el tema clar o fosc que demana el seu navegador, i canvia amb ell. + +És el valor predeterminat quan no s'ha triat cap tema predeterminat, així que una instal·lació nova segueix el navegador. En passar el punter per un dels colors de +**Color**, l'aplicació es previsualitza en aquell color; el tema que tenies torna quan el punter en surt, i no es desa res fins que no prems **Desa**. diff --git a/i18n/ca/_configure/appearance/icon.md b/i18n/ca/_configure/appearance/icon.md new file mode 100644 index 0000000..f7f7644 --- /dev/null +++ b/i18n/ca/_configure/appearance/icon.md @@ -0,0 +1,23 @@ +--- +layout: default +title: Icona +parent: Aparença +nav_order: 4 +translated_from: b469d0e284d78450ebfac22e9e596c9808e1fc16 +--- + +# Icona +{: .no_toc } + +La teva pròpia icona a la pestanya del navegador i a les adreces d'interès +{: .fs-6 .fw-300 } + +**Icona** substitueix la icona d'AnsibleForms a la pestanya del navegador i a les adreces d'interès: + +| Regla | Valor | +|---|---| +| Tipus | PNG, ICO, SVG, WEBP, GIF i JPEG | +| Mida màxima | 256 KB | +| Millor resultat | Una imatge quadrada d'almenys 64 × 64 px, o un SVG | + +Tria un fitxer a **Icona nova** i fes clic a **Puja**; **Elimina la icona personalitzada** recupera la icona predeterminada. diff --git a/i18n/ca/_configure/appearance/labels.md b/i18n/ca/_configure/appearance/labels.md new file mode 100644 index 0000000..1120462 --- /dev/null +++ b/i18n/ca/_configure/appearance/labels.md @@ -0,0 +1,79 @@ +--- +layout: default +title: Etiquetes +parent: Aparença +nav_order: 6 +redirect_from: + - /appearance/environment.html +translated_from: 2b439f61976fc2cc161250c82c629ec40713ef2c +--- + +# Etiquetes +{: .no_toc } + +Etiquetes al costat del logotip que indiquen quina instància és aquesta +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +## La llista + +Des de la 7.3.0 **Configuració > Aparença > Etiquetes** conté diverses etiquetes al costat del logotip de la capçalera, com ara PRODUCTION i EU: + +| Columna | Significat | +|---|---| +| **Activat** | Si l'etiqueta es mostra al costat del logotip i a la pàgina d'inici de sessió | +| **Etiqueta** | El seu text, mostrat com la píndola de color que mostra la capçalera | + +Les files segueixen l'ordre de la capçalera. Un clic en una fila, o **Edita** al menú de la fila, obre la pàgina de l'etiqueta; el menú de la fila també té +**Activa** o **Desactiva**, segons correspongui, **Puja** i **Baixa** per canviar l'ordre, i **Suprimeix**. + +La capçalera i la pàgina d'inici de sessió mostren les etiquetes activades en el seu ordre. Passades tres, un **+N** gris agrupa les altres al seu tooltip, +i un telèfon mostra la primera etiqueta i el **+N**. Una etiqueta desada es mostra a l'instant a tots els navegadors oberts. + +--- + +## Afegir una etiqueta + +**Afegeix etiqueta** obre un diàleg amb els dos camps de l'etiqueta, tots dos obligatoris: + +| Camp | Significat | +|---|---| +| **Etiqueta** | El text de l'etiqueta, com ara PRODUCTION | +| **Color** | Blau, verd, ambre, taronja, vermell o gris, com a mostres rodones; vermell al principi | + +Una previsualització mostra la capçalera amb totes les etiquetes activades i la nova a mesura que s'escriu. Una etiqueta nova està activada i va després de les +altres. La seva pàgina té una pestanya, **Detalls**, amb els mateixos camps, l'interruptor **Activat**, que es desa a l'instant, i la previsualització. + +--- + +## L'etiqueta d'entorn de la 7.2 + +Fins a la 7.2, **Configuració > Aparença > Entorn** definia una sola etiqueta al costat del logotip. + +Amb una sola etiqueta, PRODUCTION EU i PRODUCTION US es llegeixen totes dues com a PRODUCTION quan hi ha diverses instàncies obertes alhora. Des de la 7.3.0 +l'actualització converteix aquesta etiqueta en la primera de la llista, amb el seu text, el seu color i si es mostrava, i l'antiga adreça d'**Entorn** +obre la llista. + +--- + +## Etiquetes a la llavor de configuració + +Des de la 7.3.0 la [llavor de configuració](../seed/) declara etiquetes a la seva secció `labels`, cadascuna amb el seu text i, opcionalment, el seu color: + +```yaml +labels: + items: + - name: PRODUCTION + color: red + - name: EU + color: blue + enabled: true + position: 2 +``` + +`color` és un de `blue`, `green`, `amber`, `orange`, `red` o `grey`, i `position` les ordena, la més baixa primer. Una etiqueta declarada +a la llavor és només de lectura a la seva pàgina, com qualsevol [objecte gestionat](../seed/managed-objects.html). diff --git a/i18n/ca/_configure/appearance/links.md b/i18n/ca/_configure/appearance/links.md new file mode 100644 index 0000000..c7a657d --- /dev/null +++ b/i18n/ca/_configure/appearance/links.md @@ -0,0 +1,33 @@ +--- +layout: default +title: Enllaços +parent: Aparença +nav_order: 5 +translated_from: b17adbc1210baac2cf6786f7b0cef5e18fea8ae1 +--- + +# Enllaços +{: .no_toc } + +Els enllaços de la capçalera, els integrats i els teus +{: .fs-6 .fw-300 } + +**Enllaços** defineix els enllaços de la capçalera, per a tots els usuaris que han iniciat sessió, en dues pestanyes. + +**Integrats** té l'interruptor **Dissenyador**, desat a [`SHOW_DESIGNER`](../customization/features.html#env_SHOW_DESIGNER) i aplicat +sense reiniciar. Si es desactiva, el dissenyador desapareix per a tothom: el seu enllaç, la seva pàgina i la seva API. + +**Personalitzats** conté els teus propis enllaços, com ara una wiki, un runbook o un portal de suport. **Afegeix enllaç** afegeix una fila amb aquests camps: + +| Camp | Significat | +|---|---| +| **Icona** | La icona davant de l'etiqueta, triada d'una llista | +| **Etiqueta** | El text de l'enllaç | +| **Adreça** | Un lloc web (`https://…`) o una pàgina de l'aplicació (`/forms/all`) | +| **Pestanya nova** | Obre l'enllaç en una pestanya nova del navegador | + +Els botons d'una fila la mouen: **→** posa l'enllaç dins de l'enllaç de dalt, que llavors s'obre com a menú a la capçalera, +**←** el torna a treure a la capçalera, i les fletxes amunt i avall el mouen (un menú, amb els enllaços que conté). +Un menú no necessita cap adreça pròpia. + +La capçalera conté com a màxim 5 dels teus enllaços després dels integrats, i com a màxim 10 dins de cada menú. diff --git a/i18n/ca/_configure/appearance/logo.md b/i18n/ca/_configure/appearance/logo.md new file mode 100644 index 0000000..8287959 --- /dev/null +++ b/i18n/ca/_configure/appearance/logo.md @@ -0,0 +1,24 @@ +--- +layout: default +title: Logotip +parent: Aparença +nav_order: 3 +translated_from: 758fef67f2f704714e58065380b77f000000317f +--- + +# Logotip +{: .no_toc } + +El teu propi logotip a la capçalera +{: .fs-6 .fw-300 } + +**Logotip** substitueix el logotip d'AnsibleForms de la capçalera per la teva pròpia imatge, que es mostra en tots els temes: + +| Regla | Valor | +|---|---| +| Tipus | PNG, JPEG, WEBP, GIF i SVG | +| Mida màxima | 900 KB | +| Mida a la capçalera | Com a màxim 200 × 33 px, mantenint-ne les proporcions | + +Tria un fitxer a **Logotip nou** per previsualitzar-lo i després fes clic a **Puja**. **Logotip actual** mostra el logotip en ús i la mida +amb què el mostra la capçalera. **Elimina el logotip personalitzat** recupera el logotip predeterminat, que segueix el tema. diff --git a/i18n/ca/_configure/appearance/name.md b/i18n/ca/_configure/appearance/name.md new file mode 100644 index 0000000..abf925e --- /dev/null +++ b/i18n/ca/_configure/appearance/name.md @@ -0,0 +1,16 @@ +--- +layout: default +title: Nom +parent: Aparença +nav_order: 2 +translated_from: fa9f4116c202b7a476161e4881208eacfaadbc45 +--- + +# Nom +{: .no_toc } + +El nom de l'aplicació a la pestanya del navegador i a la pàgina d'inici de sessió +{: .fs-6 .fw-300 } + +**Nom** conté el **Nom de l'aplicació**, que es mostra a la pestanya del navegador i a la pàgina d'inici de sessió. Si és buit, la pestanya del navegador mostra +`AnsibleForms` i la pàgina d'inici de sessió no mostra cap nom. diff --git a/i18n/ca/_configure/authentication/entra-id.md b/i18n/ca/_configure/authentication/entra-id.md new file mode 100644 index 0000000..04678f9 --- /dev/null +++ b/i18n/ca/_configure/authentication/entra-id.md @@ -0,0 +1,146 @@ +--- +layout: default +title: Entra ID +parent: Autenticació +nav_order: 3 +translated_from: c5dad595f7df36cfd31a902ad0a44c7b5bb02f4e +--- + +# Entra ID +{: .no_toc } + +Inici de sessió únic amb Microsoft Entra ID (Azure AD), amb rols segons els grups d'Entra ID de l'usuari +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +## Com funciona + +Amb un proveïdor Entra ID activat, la pàgina d'inici de sessió mostra un botó d'Entra ID sota **Inicia la sessió**. Un inici de sessió segueix aquests passos: + +1. El botó envia el navegador a `/api/v2/auth/entraid`, que el redirigeix a Microsoft. +2. L'usuari inicia sessió a Microsoft, que el redirigeix de tornada a la **URL de redirecció** amb un codi d'autorització. El servidor + intercanvia aquest codi amb Microsoft per l'ID token i un access token per a Microsoft Graph. +3. El servidor llegeix els grups de l'usuari de Microsoft Graph (`/v1.0/me/transitiveMemberOf`), de manera que els grups niats també compten. +4. Els grups es filtren amb el **Filtre de grups** sobre el seu nom de visualització, i cada grup que es conserva es desa dues vegades, + com a `azuread/` i com a `azuread/`. + +El nom d'usuari és el claim `upn` del token, p. ex. `jdoe@example.com`, o el claim `preferred_username` quan el token +no té `upn`; en un compte de feina tots dos contenen el mateix valor. + +--- + +## Registrar l'aplicació + +AnsibleForms necessita un registre d'aplicació a l'Entra admin center, a **App registrations > New registration**: + +1. Dona-li un nom, tria **Accounts in this organizational directory only** com a tipus de compte admesos i afegeix un + URI de redirecció de tipus **Web**: `https://af.example.com/api/v2/auth/entraid/callback`. +2. A **Certificates & secrets**, crea un secret de client i copia'n el valor; només es mostra una vegada. +3. A **API permissions**, afegeix els permisos **delegated** de Microsoft Graph `User.Read` i `GroupMember.Read.All`, + i concedeix-los el consentiment d'administrador. +4. A la pàgina **Overview**, anota l'**Application (client) ID** i el **Directory (tenant) ID**. + +L'URI de redirecció és l'adreça amb què els usuaris arriben a AnsibleForms, seguida de `/api/v2/auth/entraid/callback`. +Amb [`BASE_URL`](../customization/server.html#env_BASE_URL) `/forms`, passa a ser +`https://af.example.com/forms/api/v2/auth/entraid/callback`. Ha de coincidir exactament amb l'**URI de redirecció** de la +credencial del proveïdor. + +Fins a la 7.2.0 el camí era `/api/v2/auth/azureadoauth2/callback`. Continua funcionant des de la 7.3.0, així que un registre existent +no necessita cap canvi; una credencial amb l'**URI de redirecció** buit utilitza el camí nou, així que en aquest cas afegeix-lo al registre. + +AnsibleForms llegeix els grups de Graph i no utilitza cap claim de grups al token, així que no cal configurar cap claim de grups +al registre. + +--- + +## Afegir el proveïdor + +Afegeix el proveïdor a **Accés > SSO**: un assistent en demana els camps en quatre passos, amb **Microsoft Entra ID** al pas **Tipus**: + +| Pas | Camp | Significat | +|---|---|---| +| Detalls | Nom, Descripció | Un nom únic per al proveïdor i una descripció opcional | +| Tipus | Proveïdor | **Microsoft Entra ID**; es fixa quan es crea i no canvia | +| Credencials | Credencial | Una credencial **Microsoft Entra ID** de [Connexions > Credencials](../credentials.html), vegeu més avall | +| Grups | Filtre de grups | Expressió regular; només es conserven els grups el nom de visualització dels quals coincideix. Buit conserva tots els grups | + +La credencial conté el registre de l'aplicació, així que només un admin la pot afegir o canviar: + +| Camp | Significat | +|---|---| +| ID del tenant | Obligatori. El Directory (tenant) ID, un GUID, o un dels dominis del tenant. Només els usuaris d'aquest tenant poden iniciar sessió | +| ID del client | L'Application (client) ID | +| Secret del client | El valor del secret de client, desat xifrat o llegit d'un [magatzem de secrets](../secret-stores/) | +| URI de redirecció | Tal com està registrat, p. ex. `https://af.example.com/api/v2/auth/entraid/callback`. Buit: la URL de l'aplicació i el camí de retorn | + +Una credencial amb l'ID del tenant buit es rebutja quan es desa. Els endpoints multitenant `common`, `organizations` +i `consumers` es rebutgen quan es desa el proveïdor que nomena la credencial, perquè permetrien iniciar sessió a usuaris de qualsevol +tenant de Microsoft. En iniciar sessió, el servidor també comprova que el token ve del tenant configurat. Un proveïdor +desat abans sense ID del tenant no deixa entrar ningú: fins que no s'emplena l'ID del tenant, el servidor registra +`Could not enable Microsoft Entra ID: set the tenant id to your tenant ('' would let any Microsoft tenant log in)`. + +Fins a la 7.2.0 el tenant, l'ID del client, el secret i la URL de redirecció eren camps del proveïdor. L'actualització a la 7.3.0 els trasllada a una +credencial anomenada `-sso`, vegeu [Adreces a les credencials](../credentials/types.html#addresses-in-credentials). +Tria una credencial per a cada proveïdor nou: el servidor encara accepta un proveïdor amb el seu propi ID de client i secret d'abans +de la 7.3.0, que hi inicia sessió fins que es tria una credencial. + +Només hi ha un proveïdor Entra ID activat alhora, aquell amb què inicia sessió el botó d'Entra ID. **Activa** al menú de fila d'un altre, +o el seu interruptor **Activat**, desactiva els altres del seu tipus; la columna **Activat** de la llista mostra quin s'està fent servir. Un proveïdor +també es pot saltar la pàgina d'inici de sessió, vegeu [Activar i desactivar l'inici de sessió únic](./#switching-single-sign-on). En desar, s'aplica a l'instant, sense reiniciar. + +--- + +## Assignació a rols + +A config.yaml, un grup d'Entra ID és `entraid/` o `entraid/`, i un usuari és `entraid/`. +L'object id és únic al tenant, així que és l'opció més segura; un nom de visualització és més fàcil de llegir: + +```yaml +roles: + - name: admin + groups: + - local/admins + - entraid/0b6c8e1a-2f4d-4c7e-9a3b-5d1e7f2a4c6b + - name: operator + groups: + - entraid/AF-Operators + users: + - entraid/jdoe@example.com +``` + +Fins a la 7.2.0 el prefix era `azuread/`. En un rol continua coincidint amb els mateixos membres des de la 7.3.0 i s'elimina a la 8.0; l'editor +de rols escriu `entraid/`. Només els rols accepten `entraid/`: els grups de l'usuari es desen com a `azuread/` i +`azuread/`, i així els mostren la pàgina del perfil i l'extravar `ansibleforms_user`. Un **Filtre de grups** com ara `^AF-` conserva només els grups que fan servir els teus rols; vegeu [Rols](../config/roles.html). Des de la 7.1.0 +el token d'inici de sessió ja no porta els grups, de manera que la seva mida ja no creix amb ells. El filtre continua sent important per als +usuaris amb molts grups: a cada inici de sessió es comparen menys grups amb els rols, i el +[registre del directori](../users-and-groups/directory.html) de l'usuari només llista els grups que compten. Abans de la 7.1.0, +un usuari amb cent grups o més el necessita per veure algun formulari, vegeu +[Formularis i tasques buits després d'un inici de sessió únic](../troubleshooting.html#empty-forms-and-jobs-after-a-single-sign-on-http-431). + +--- + +## Endpoint de Microsoft Graph + +Per defecte, el servidor inicia la sessió dels usuaris a `https://login.microsoftonline.com` i crida Microsoft Graph a `https://graph.microsoft.com`: + +| Variable | Què canvia | +|---|---| +| [`ENTRA_AUTHORITY_URI`](../customization/security.html#env_ENTRA_AUTHORITY_URI) | L'autoritat d'inici de sessió, per a un núvol nacional com ara `https://login.microsoftonline.us` | +| [`ENTRA_GRAPH_URI`](../customization/security.html#env_ENTRA_GRAPH_URI) | L'endpoint de Graph del qual es llegeixen els grups, com ara `https://graph.microsoft.us` | + +Totes dues reben un URI base sense barra final, i són noves a la 7.3.0. `AZURE_AUTHORITY_URI` i `AZURE_GRAPH_URI` encara es llegeixen +quan no estan definides, amb un avís al registre, i s'eliminen a la 8.0. El servidor ha de poder arribar a Graph: un inici de sessió falla quan no es poden llegir els grups. + +--- + +## Limitacions + +Els usuaris d'Entra ID inicien sessió amb Microsoft, així que algunes coses funcionen de manera diferent que amb els comptes locals i LDAP: + +- No tenen contrasenya a AnsibleForms, així que no la hi poden canviar; un [token d'API](../profile/api-token.html) es crea des de la seva sessió. +- Els noms de visualització no són únics a Entra ID: dos grups amb el mateix nom corresponen al mateix rol. Nomena el grup pel seu + object id al rol, `entraid/`, perquè només coincideixi amb aquest grup. diff --git a/i18n/ca/_configure/authentication/index.md b/i18n/ca/_configure/authentication/index.md new file mode 100644 index 0000000..7f2cb00 --- /dev/null +++ b/i18n/ca/_configure/authentication/index.md @@ -0,0 +1,108 @@ +--- +layout: default +title: Autenticació +nav_order: 3 +has_children: true +has_toc: false +permalink: /authentication/ +translated_from: 024cff3760cf611daeacea8aea7d72b85c0a6d17 +--- + +# Autenticació +{: .no_toc } + +Tria com inicien sessió els usuaris, i com el seu compte i els seus grups porten als rols +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +## Mètodes d'inici de sessió + +AnsibleForms admet quatre mètodes d'inici de sessió, i n'hi pot haver diversos d'actius alhora: + +| Mètode | Quan fer-lo servir | Pàgina | +|---|---|---| +| Comptes locals | L'admin integrat, comptes de servei, equips petits, o com a alternativa quan el directori no està disponible. | [Comptes locals](local.html) | +| LDAP | Els usuaris i els grups són a Active Directory, OpenLDAP o un altre directori LDAP. | [LDAP](ldap.html) | +| Entra ID | Els usuaris inicien sessió amb el seu compte de Microsoft 365 / Entra ID (inici de sessió únic). | [Entra ID](entra-id.html) | +| OIDC | Inici de sessió únic a través d'un altre proveïdor OpenID Connect, com ara Keycloak. | [OIDC](oidc.html) | + +Els comptes locals i LDAP es configuren a **Accés > Usuaris**, **Grups** i **LDAP**; Entra ID i OIDC a +**Accés > SSO**. + +--- + +## Com tria el mètode un inici de sessió + +La pàgina d'inici de sessió té un formulari de nom d'usuari i contrasenya, més un botó per cada proveïdor d'inici de sessió únic activat: + +- **El nom d'usuari i la contrasenya** es comproven primer amb els usuaris locals. Només quan cap usuari local no té aquest nom, i LDAP + està activat, es prova el directori. Un usuari local amb una contrasenya incorrecta es rebutja sense consultar LDAP. +- **Els botons d'Entra ID i OpenID** apareixen sota **Inicia la sessió** quan hi ha un proveïdor d'aquest tipus activat. Envien el navegador al + proveïdor i de tornada; cap contrasenya no arriba a AnsibleForms. + +Només pot haver-hi activat alhora un proveïdor Entra ID i un proveïdor OIDC: activar-ne un desactiva els altres del seu tipus. +Un inici de sessió fallit amb usuari i contrasenya mostra sempre el mateix missatge genèric; el motiu és al registre del servidor i al registre d'auditoria. + +--- + +## Activar i desactivar l'inici de sessió únic + +Des de la 7.3.0 cada proveïdor d'**Accés > SSO** té dos interruptors propis, que s'apliquen sense reiniciar: + +| Interruptor | Efecte | +|---|---| +| **Activat** | Mostra el botó del proveïdor a la pàgina d'inici de sessió i n'accepta l'inici de sessió. Activar-lo desactiva els altres proveïdors del seu tipus. | +| **Salta la pàgina d'inici de sessió** | Els usuaris van directament a aquest proveïdor, sense la pàgina d'inici de sessió, mentre el proveïdor està activat. Activar-lo en un proveïdor el desactiva en els altres; apareix en gris en un proveïdor desactivat. | + +El formulari d'usuari i contrasenya continua accessible a `/login?local`, per a l'admin local o quan el proveïdor falla, +i es mostra després de tancar la sessió i quan un inici de sessió únic torna amb un error. + +Les variables `ENABLE_SSO` i `SSO_AUTO_LOGIN` s'eliminen a la 7.3.0. La primera arrencada de la 7.3.0 les llegeix una vegada, i +registra un avís a cada arrencada mentre continuïn definides, així que treu-les de l'entorn després de l'actualització: + +| Variable abans de la 7.3.0 | Què fa l'actualització | +|---|---| +| `ENABLE_SSO=0` | Desactiva tots els proveïdors: continuen configurats, sense botó a la pàgina d'inici de sessió | +| `SSO_AUTO_LOGIN=1` | Activa **Salta la pàgina d'inici de sessió** al proveïdor activat, quan n'hi ha exactament un d'activat i `ENABLE_SSO` no és `0` | + +--- + +## De l'usuari als rols + +Cada inici de sessió produeix un usuari amb un **tipus** (`local`, `ldap`, `azuread` o `oidc`), un nom d'usuari i una llista de grups. +Cada grup rep el prefix del seu tipus, de manera que un grup d'Entra ID es desa i es mostra com a `azuread/...`: + +| Mètode d'inici de sessió | Nom d'usuari | Grups | +|---|---|---| +| Local | el nom d'usuari local | `local/`, un per cada grup local de l'usuari | +| LDAP, directori `main` | el valor de l'Username Attribute | `ldap/`, el CN de cada grup que retorna el directori | +| LDAP, un altre directori | `/` | `ldap//`, vegeu [Diversos directoris](ldap.html#several-directories) | +| Entra ID | el claim `upn`, o `preferred_username` quan el token no té `upn` | `azuread/` i `azuread/` de cada grup, llegits de Microsoft Graph | +| OIDC | el claim `preferred_username` | `oidc/`, del claim `groups` de l'ID token | + +Els [rols](../config/roles.html) de config.yaml comparen després aquests valors: un rol s'aplica quan un dels seus `groups` és un +dels grups de l'usuari, o quan el seu `users` conté `/`. Tots els usuaris reben també el rol `default`. Des de la 7.3.0 un +rol nomena un membre d'Entra ID com a `entraid/` o `entraid/`, que coincideix amb el valor `azuread/` desat; `azuread/` +en un rol continua funcionant i s'elimina a la 8.0. El perfil i les extravars de la tasca continuen mostrant `azuread/`. + +```yaml +roles: + - name: admin + groups: + - local/admins + - ldap/AF-Admins + - entraid/AF-Admins + - name: operator + groups: + - oidc/af-operators + users: + - ldap/jdoe +``` + +La pàgina del **perfil** d'un usuari llista el tipus d'inici de sessió, els grups i els rols, que és la manera més ràpida de comprovar una assignació. +L'opció de rol `allowLogin` pot rebutjar l'inici de sessió dels usuaris que no coincideixen amb cap rol: posa-la a `false` a `default` i a +`true` als rols que poden iniciar sessió. diff --git a/i18n/ca/_configure/authentication/ldap.md b/i18n/ca/_configure/authentication/ldap.md new file mode 100644 index 0000000..ab90097 --- /dev/null +++ b/i18n/ca/_configure/authentication/ldap.md @@ -0,0 +1,240 @@ +--- +layout: default +title: LDAP +parent: Autenticació +nav_order: 2 +translated_from: a4089d681ad976e31e7ddefb29588bd3ca334dab +--- + +# LDAP +{: .no_toc } + +Deixa que els usuaris del directori iniciïn sessió amb la seva pròpia contrasenya, i dona'ls rols a través dels seus grups del directori +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +## Com funciona + +AnsibleForms es connecta al directori amb un compte de bind, cerca l'usuari i després fa bind com a aquest usuari per comprovar +la contrasenya: + +1. L'usuari inicia sessió amb nom d'usuari i contrasenya. Quan cap usuari **local** no té aquest nom, es prova LDAP. +2. AnsibleForms fa bind amb el compte de bind de la credencial del directori, i cerca a la **Base de cerca** una entrada l'**Atribut del + nom d'usuari** de la qual sigui igual al nom d'usuari. +3. Fa bind com a l'entrada trobada, amb la contrasenya que s'ha escrit. +4. Els grups es llegeixen de l'entrada (o d'una cerca de grups), es filtren i se'ls afegeix el prefix `ldap/`. + +Un nom d'usuari en format UPN (`jdoe@example.com`) que no troba cap usuari es torna a provar una vegada amb la part anterior a l'`@`, de manera que els usuaris +poden iniciar sessió amb qualsevol de les dues formes encara que l'Atribut del nom d'usuari contingui el nom curt. Una contrasenya incorrecta no es torna a provar mai. + +Una mateixa configuració serveix per a Active Directory, OpenLDAP i d'altres; des de la 7.3.0 hi pot haver [diversos directoris](#several-directories). + +--- + +## Configuració + +Des de la 7.3.0 la configuració és per directori. **Accés > LDAP** llista els directoris, en l'ordre en què es cerca un nom d'usuari sense directori: + +![Accés > LDAP](../assets/screenshots/ldap.jpg) + +| Menú de fila | Què fa | +|---|---| +| Edita | Obre la pàgina del directori | +| Prova la connexió | Prova un inici de sessió amb un nom d'usuari i una contrasenya de prova, vegeu [Provar la connexió](#testing-the-connection) | +| Activa, Desactiva | Activa o desactiva el directori; `main` es desactiva en lloc de suprimir-se | +| Puja, Baixa | Canvia el seu lloc a l'ordre de cerca | +| Suprimeix | Elimina el directori; es mostra però desactivat a `main` | + +Afegir un directori en demana els camps en quatre passos, les pestanyes de la seva pàgina. **Detalls** conté **Activat**, el **Nom** i una **Descripció**: + +| Pestanya | Ajust | Significat | +|---|---|---| +| Credencials | Credencial | Obligatori. Una credencial `ldap` de [Connexions > Credencials](../credentials.html), que conté la connexió, vegeu més avall | +| Usuaris | Base de cerca | DN on comença la cerca d'usuaris, p. ex. `OU=Users,DC=example,DC=com`. També es cerquen els subarbres | +| Usuaris | Atribut del nom d'usuari | Atribut que es compara amb el nom d'inici de sessió: `sAMAccountName` a AD (el predeterminat), `uid` a OpenLDAP | +| Usuaris | Atribut de correu | Atribut que conté l'adreça de correu, normalment `mail` | +| Usuaris | Dominis d'inici de sessió | Dominis els inicis de sessió `user@domain` dels quals van directament a aquest directori, vegeu [Diversos directoris](#several-directories) | +| Grups | Atribut de grups | Atribut de l'entrada de l'usuari que conté els grups (`memberOf`, el predeterminat), o `groups` amb una cerca de grups | +| Grups | Base de cerca de grups | DN on comença la cerca de grups | +| Grups | Classe de grup | objectClass dels grups, p. ex. `group`, `groupOfNames` o `posixGroup` | +| Grups | Atribut de membre del grup | Atribut d'un grup que llista els seus membres, p. ex. `member`, `uniqueMember` o `memberUid`; predeterminat `member` | +| Grups | Atribut d'usuari del membre del grup | Atribut de l'usuari que contenen aquests valors de membre, p. ex. `dn` o `uid`; predeterminat `dn` | +| Grups | Filtre de grups | Expressió regular; només es conserven els grups el nom dels quals coincideix. Buit conserva tots els grups | + +Els valors predeterminats dels tres últims camps de grup només s'apliquen quan es fa servir la cerca de grups, vegeu la secció següent. + +La credencial `ldap` conté com s'arriba al directori i amb quin compte s'hi cerca: + +| Camp | Significat | +|---|---| +| Servidors | Un per camp, com a `host`, `host:port` o `ldaps://host:port`, provats en aquest ordre: quan no es pot arribar a un, es prova el següent | +| Port | `389` per a LDAP sense xifrar, `636` per a LDAPS | +| Activa TLS | Connectar amb LDAPS (`ldaps://`). StartTLS al port 389 no és compatible | +| Ignora els certificats | Omet la validació del certificat del servidor. Només es mostra amb **Activa TLS** | +| Certificat | El certificat de client que AnsibleForms presenta als servidors, en PEM, quan es comproven els certificats | +| Paquet de CA | El certificat o els certificats de CA que han signat el certificat del servidor, en PEM, quan es comproven els certificats | +| DN de l'usuari de bind | El DN del compte de servei que cerca al directori | +| Contrasenya de l'usuari de bind | La seva contrasenya, desada xifrada o llegida d'un [magatzem de secrets](../secret-stores/) | + +Només un admin pot afegir o canviar una credencial `ldap`, vegeu [Qui pot canviar una credencial](../credentials.html#who-may-change-a-credential). +Fins a la 7.2.0 els servidors, el TLS i el compte de bind eren camps de la configuració LDAP. L'actualització a la 7.3.0 els trasllada a una credencial, +vegeu [Adreces a les credencials](../credentials/types.html#addresses-in-credentials): + +| El directori abans de l'actualització | On van els seus servidors | +|---|---| +| El seu propi DN i contrasenya de bind, sense credencial | Una credencial `ldap` nova anomenada `-ldap`, com ara `main-ldap` | +| Una credencial sense servidors | A aquesta credencial | +| Una credencial que ja conté altres servidors | Una còpia de la credencial anomenada `-`, que el directori passa a nomenar | + +Un nom que ja està agafat rep `-2`, `-3`, etc. Un directori de la llavor de configuració es deixa tal com està: la llavor n'és la propietària. + +--- + +## Grups + +Els grups vénen d'un de dos llocs, i l'**Atribut de grups** decideix quin es fa servir: + +- **Un atribut de l'entrada de l'usuari**, normalment `memberOf`. És la configuració habitual per a Active Directory, i per a + OpenLDAP amb l'overlay `memberof`. +- **Una cerca de grups**, per a directoris sense `memberOf`. Només s'executa quan **Base de cerca de grups** i **Classe de grup** + estan tots dos definits: AnsibleForms cerca llavors grups d'aquesta classe l'**Atribut de membre del grup** dels quals contingui + l'**Atribut d'usuari del membre del grup** de l'usuari, i desa el resultat a l'atribut `groups`. Posa **Atribut de grups** a `groups` + per fer-la servir. + +{: .note } +> Amb **Atribut de grups** `memberOf`, una cerca de grups configurada s'executa però el seu resultat no s'utilitza per als rols. + +Cada grup és un DN, i AnsibleForms en conserva el primer CN: `CN=AF-Admins,OU=Groups,DC=example,DC=com` passa a ser `AF-Admins`. +Després s'aplica el **Filtre de grups** a aquest nom, i els grups que queden reben el prefix `ldap/`: `ldap/AF-Admins`. + +En directoris grans el filtre manté petits els tokens i les tasques; una expressió regular no vàlida conserva tots els grups i es registra. + +--- + +## Assignació a rols + +A config.yaml, un grup LDAP és `ldap/` i un usuari LDAP és `ldap/`, tots dos distingeixen majúscules i minúscules: + +```yaml +roles: + - name: admin + groups: + - local/admins + - ldap/AF-Admins + - name: operator + groups: + - ldap/AF-Operators + users: + - ldap/jdoe +``` + +El nom d'usuari és el valor de l'**Atribut del nom d'usuari** tal com el retorna el directori, no tal com l'ha escrit l'usuari. +Vegeu [Rols](../config/roles.html) per a les opcions dels rols. + +--- + +## Diversos directoris + +Des de la 7.3.0 hi pot haver diversos directoris, cadascun amb els seus propis servidors, usuaris i grups. Els seus noms distingeixen els seus membres: + +| Directori | Nom d'usuari | Grups | En un rol | +|---|---|---|---| +| `main` | `jdoe` | `ldap/AF-Admins` | `ldap/jdoe`, `ldap/AF-Admins` | +| Qualsevol altre, com ara `corp` | `corp/jdoe` | `ldap/corp/AF-Admins` | `ldap/corp/jdoe`, `ldap/corp/AF-Admins` | + +Un usuari nomena el directori en iniciar sessió com a `corp\jdoe` o `corp/jdoe`, o inicia sessió amb una adreça d'un domini que és +del directori. Un nom d'usuari sense directori es prova a cada directori activat, en el seu ordre, i també un nom com ara `other\jdoe` quan cap +directori no es diu `other`: llavors es cerca tal com s'ha escrit. + +Decideix el primer directori que coneix l'usuari: una contrasenya incorrecta en aquest és la resposta, i el directori següent no es +prova, ja que podria contenir una altra persona amb aquest nom. Un directori al qual no es pot arribar s'omet. + +El directori anomenat `default` fins a la 7.2.0 es diu `main` des de la 7.3.0: l'actualització el reanomena, i una instal·lació nova comença +amb `main`. Els seus membres conserven els seus noms curts, així que els rols que els nomenen no necessiten cap canvi. El directori `main` no es pot +reanomenar, i el nom d'un directori només conté lletres, xifres, `-` i `_`. + +--- + +## Provar la connexió + +**Prova la connexió** demana un nom d'usuari i una contrasenya de prova, i intenta un inici de sessió amb la configuració de la pantalla, desada o no. +Si funciona, mostra l'entrada de l'usuari al directori, que t'indica els noms exactes dels atributs i els DN dels grups que has de fer servir. + +Un usuari de prova que no existeix també informa d'èxit: la connexió i el compte de bind funcionen, només que l'usuari no es +troba. Errors habituals: + +| Missatge | Causa | +|---|---| +| `Bad server or port (connection failed)` | El nom de host no es resol o no es pot arribar al port. | +| `Wrong binding credentials` | El DN o la contrasenya de bind de la credencial del directori són incorrectes. | +| `Unable to verify the certificate` | El certificat del servidor no està signat pel Paquet de CA de la credencial. | +| `Certificate is not valid` | El Certificat o el Paquet de CA de la credencial no contenen un certificat PEM vàlid. | + +--- + +## Exemple amb Active Directory + +Aquest exemple es connecta a dos controladors de domini per LDAPS i només conserva els grups el nom dels quals comença per `AF-`: + +| Ajust | Valor | +|---|---| +| Credencial > Servidors | `dc01.example.com`, i després `dc02.example.com` | +| Credencial > Port | `636` | +| Credencial > Activa TLS | activat | +| Credencial > Ignora els certificats | desactivat, amb un certificat de client i la cadena de CA de la CA de l'empresa | +| Credencial > DN de l'usuari de bind | `CN=svc-ansibleforms,OU=Service Accounts,DC=example,DC=com` | +| Base de cerca | `OU=Users,DC=example,DC=com` | +| Atribut de correu | `mail` | +| Atribut del nom d'usuari | `sAMAccountName` | +| Atribut de grups | `memberOf` | +| Filtre de grups | `^AF-` | + +Els membres de `CN=AF-Operators,…` coincideixen amb els rols que fan servir `ldap/AF-Operators`, i inicien sessió com a `jdoe` o `jdoe@example.com`. + +--- + +## Exemple amb OpenLDAP + +Aquest exemple fa servir una cerca de grups sobre entrades `groupOfNames`, així que funciona sense l'overlay `memberof`: + +| Ajust | Valor | +|---|---| +| Credencial > Servidors | `ldap.example.com` | +| Credencial > Port | `636` | +| Credencial > Activa TLS | activat | +| Credencial > DN de l'usuari de bind | `cn=readonly,dc=example,dc=com` | +| Base de cerca | `ou=people,dc=example,dc=com` | +| Atribut de correu | `mail` | +| Atribut del nom d'usuari | `uid` | +| Atribut de grups | `groups` | +| Base de cerca de grups | `ou=groups,dc=example,dc=com` | +| Classe de grup | `groupOfNames` | +| Atribut de membre del grup | `member` | +| Atribut d'usuari del membre del grup | `dn` | + +Un usuari llistat a `cn=af-admins,ou=groups,dc=example,dc=com` rep el grup `ldap/af-admins`. Per a grups `posixGroup`, +fes servir **Atribut de membre del grup** `memberUid` i **Atribut d'usuari del membre del grup** `uid`. + +Amb l'overlay `memberof`, deixa buits els camps de cerca de grups i posa **Atribut de grups** a `memberOf`. + +--- + +## Errors habituals + +La majoria dels problemes amb LDAP es redueixen a un d'aquests: + +- **Un usuari local amb el mateix nom.** Els usuaris locals es comproven primer, així que mai no es consulta el directori per a aquest nom. +- **Cap grup, o grups equivocats.** L'Atribut de grups ha d'existir (`groups` amb una cerca de grups); `memberOf` no segueix els grups niats. +- **Noms de grup que no coincideixen.** Fes servir `ldap/` amb les mateixes majúscules i minúscules, i comprova que el Filtre de grups conserva el grup. +- **DN de grup que no comencen per un CN.** Només s'utilitza el primer valor `CN=` com a nom del grup, així que tots els DN de grup + han de començar per `CN=` (o `cn=`). +- **Certificats.** El TLS necessita els dos camps de certificat de la credencial i un nom de servidor que coincideixi; Ignora els certificats és només per a proves. +- **Una configuració que no es pot desar.** Quan un directori ve de la [llavor de configuració](../seed/managed-objects.html), la seva pàgina + és només de lectura: canvia el fitxer de la llavor. + +Un inici de sessió fallit mostra un missatge genèric. El servidor en registra el motiu i el conserva al registre d'auditoria, i per a Active +Directory es tradueix a partir del codi del directori, p. ex. `Wrong password`, `Account locked` o `Password expired`. diff --git a/i18n/ca/_configure/authentication/local.md b/i18n/ca/_configure/authentication/local.md new file mode 100644 index 0000000..1e95c83 --- /dev/null +++ b/i18n/ca/_configure/authentication/local.md @@ -0,0 +1,108 @@ +--- +layout: default +title: Comptes locals +parent: Autenticació +nav_order: 1 +translated_from: 002a371f2b4dbe5cc9c99ee569b8cf17a2a4ac88 +--- + +# Comptes locals +{: .no_toc } + +L'admin integrat, i els usuaris i grups desats a la base de dades d'AnsibleForms +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +## L'admin integrat + +Cada arrencada crea el grup local `admins` i l'usuari admin si no existeixen; tres variables controlen l'admin: + +| Variable | Predeterminat | Significat | +|---|---|---| +| [`ADMIN_USERNAME`](../customization/server.html#env_ADMIN_USERNAME) | `admin` | Nom d'usuari de l'admin, creat al grup `admins` quan cap usuari no té aquest nom. | +| [`ADMIN_PASSWORD`](../customization/server.html#env_ADMIN_PASSWORD) | `AnsibleForms!123` | Contrasenya que rep l'admin quan es crea (o es restableix). | +| [`REINIT_ADMIN`](../customization/server.html#env_REINIT_ADMIN) | `0` | `1` restableix la contrasenya de l'admin a `ADMIN_PASSWORD` i el torna a posar a `admins`. | + +`ADMIN_PASSWORD` només s'utilitza quan l'usuari es crea o es restableix: canviar-la després no fa res per si sol. + +Un usuari local que inicia sessió amb la contrasenya predeterminada pública `AnsibleForms!123` només la pot canviar. El navegador obre una +pàgina de canvi de contrasenya que no es pot tancar, i el servidor respon a qualsevol altra petició amb `403` (codi +`password_change_required`) fins que es canvia la contrasenya. La contrasenya nova ha de ser diferent de la predeterminada; després del +canvi, l'usuari torna a iniciar sessió amb ella. Defineix `ADMIN_PASSWORD` amb el teu propi valor abans de la primera arrencada per saltar-te aquest pas. + +Canviar `ADMIN_USERNAME` després de la primera arrencada crea un segon usuari admin amb aquest nom; l'antic es conserva. + +{: .warning } +> `REINIT_ADMIN=1` restableix la contrasenya a **cada** arrencada mentre està definida. Fes-la servir per recuperar una contrasenya d'admin perduda, +> i després treu-la i reinicia. + +--- + +## Usuaris i grups + +Els usuaris i grups locals es gestionen a **Accés > Usuaris** i **Accés > Grups**. Un usuari té aquests camps: + +| Camp | Significat | +|---|---| +| Nom d'usuari | El nom d'inici de sessió. Ha de ser únic. | +| Descripció | Opcional. | +| Contrasenya | Es desa com a hash. Canvia-la més endavant amb l'acció **Canvia la contrasenya**. | +| Correu electrònic | Opcional. | +| Grup | El primer grup local de l'usuari. Afegeix-ne més a la pestanya **Grups** de la pàgina de l'usuari. | + +Els usuaris locals canvien la seva pròpia contrasenya al seu perfil; els altres usuaris ho fan al seu directori o proveïdor d'identitat. + +Un usuari pot pertànyer a diversos grups, i rep els rols de tots ells. La pestanya **Grups** de la pàgina d'un usuari afegeix i +treu grups, igual que la pestanya **Usuaris** de la pàgina d'un grup. Un usuari conserva almenys un grup: l'últim no es pot +treure. + +Un grup que encara té usuaris no es pot suprimir: primer treu-ne els usuaris. El grup `admins` no es pot suprimir ni +reanomenar mai, i l'usuari `admin` no es pot suprimir mai. + +--- + +## Permetre l'inici de sessió + +La pestanya **Detalls** de la pàgina d'un usuari té un interruptor **Permet l'inici de sessió**, que també s'ofereix com a **Bloqueja l'inici de sessió** i **Permet +l'inici de sessió** al menú de fila de la llista d'usuaris. Existeix tant per als usuaris locals com per als usuaris LDAP i SSO: + +- **Activat**: l'usuari inicia sessió amb normalitat. +- **Desactivat**: les sessions de l'usuari acaben a l'instant i es rebutja qualsevol inici de sessió, fins que un admin el torni a activar. La pàgina + demana confirmació abans. + +L'interruptor no es pot desactivar per a l'usuari `admin`, la via per tornar a entrar, ni el pot desactivar un admin per al seu propi compte. La pàgina +d'un usuari LDAP o SSO també té **Tanca les sessions**, que tanca la sessió de l'usuari a tot arreu sense bloquejar-lo. + +--- + +## Assignació a rols + +Els rols nomenen els grups locals com a `local/` i els usuaris com a `local/`; per defecte `admins` rep `admin`: + +```yaml +roles: + - name: admin + groups: + - local/admins + - name: operator + groups: + - local/operators + users: + - local/svc-backup +``` + +Mantén `local/admins` al rol `admin`, perquè l'admin integrat sempre pugui iniciar sessió, fins i tot quan el directori o el +proveïdor d'identitat no estan disponibles. Quan config.yaml no es pot carregar de cap manera, els membres de `local/admins` continuen rebent el +rol `admin`, així que pots iniciar sessió i corregir-ho. Vegeu [Rols](../config/roles.html) per a les opcions dels rols. + +--- + +## Comptes locals i LDAP + +Un inici de sessió amb usuari i contrasenya comprova els usuaris locals abans que LDAP. Quan un usuari local té el mateix nom que un usuari +del directori, el compte local sempre guanya i la contrasenya del directori no funciona per a aquest nom. Dona als comptes locals noms +que no puguin coincidir amb comptes del directori, per exemple amb un prefix `svc-`. diff --git a/i18n/ca/_configure/authentication/oidc.md b/i18n/ca/_configure/authentication/oidc.md new file mode 100644 index 0000000..34b3f60 --- /dev/null +++ b/i18n/ca/_configure/authentication/oidc.md @@ -0,0 +1,133 @@ +--- +layout: default +title: OIDC +parent: Autenticació +nav_order: 4 +translated_from: 5451df911884021544dea5ffbaa7228a7a4435ef +--- + +# OIDC +{: .no_toc } + +Inici de sessió únic amb un proveïdor OpenID Connect com ara Keycloak, amb rols segons un claim de grups +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +## Com funciona + +Amb un proveïdor OIDC activat, la pàgina d'inici de sessió mostra un botó d'OpenID sota **Inicia la sessió**. Un inici de sessió segueix aquests passos: + +1. El botó envia el navegador a `/api/v2/auth/oidc`, que el redirigeix al proveïdor (flux de codi d'autorització + amb PKCE). +2. L'usuari inicia sessió al proveïdor, que el redirigeix de tornada a la **URL de redirecció**. +3. El servidor intercanvia el codi per tokens i llegeix els claims de l'ID token. +4. El nom d'usuari és el claim `preferred_username`, i cada valor del claim `groups` que passa el + **Filtre de grups** es converteix en un grup `oidc/`. + +AnsibleForms demana els scopes `openid profile email`; els scopes no són configurables. Tancar la sessió d'AnsibleForms +també envia el navegador a l'endpoint de final de sessió del proveïdor, quan el proveïdor en publica un. + +{: .note } +> OIDC s'ha provat amb Keycloak. Altres proveïdors funcionen quan compleixen els requisits següents. + +--- + +## Requisits del proveïdor + +El proveïdor ha d'oferir el descobriment d'OpenID Connect i un client confidencial per a AnsibleForms: + +- **Descobriment**: AnsibleForms llegeix `/.well-known/openid-configuration`, així que l'emissor ha de ser accessible des + del servidor d'AnsibleForms, per HTTPS. +- **Un client confidencial** amb el flux de codi d'autorització, un ID de client i un secret de client. +- **L'URI de redirecció** `https://af.example.com/api/v2/auth/oidc/callback`, és a dir, l'adreça amb què els usuaris arriben a + AnsibleForms seguida de `/api/v2/auth/oidc/callback`. Amb [`BASE_URL`](../customization/server.html#env_BASE_URL) + `/forms`, passa a ser `https://af.example.com/forms/api/v2/auth/oidc/callback`. +- **Un claim `groups` a l'ID token**, amb una llista de noms de grup. Sense aquest claim, l'usuari no rep cap grup OIDC. +- **Un claim `preferred_username`**, que es converteix en el nom d'usuari. + +--- + +## Exemple amb Keycloak + +Aquest exemple utilitza un realm `example` a `https://keycloak.example.com`; l'emissor és llavors +`https://keycloak.example.com/realms/example`. En aquest realm: + +1. A **Clients**, crea un client OpenID Connect amb el client ID `ansibleforms`. Activa **Client authentication**, + mantén **Standard flow** i posa a **Valid redirect URIs** `https://af.example.com/api/v2/auth/oidc/callback`. +2. A la pestanya **Credentials** del client, copia el **Client secret**. +3. A la pestanya **Client scopes**, obre `ansibleforms-dedicated` i afegeix un mapper **By configuration > Group Membership**, + amb **Token Claim Name** `groups`, **Full group path** desactivat i **Add to ID token** activat. + +Amb **Full group path** activat, el claim conté camins com ara `/af-admins`, i llavors el rol ha d'utilitzar `oidc//af-admins`. + +--- + +## Afegir el proveïdor + +Afegeix el proveïdor a **Accés > SSO**: un assistent en demana els camps en quatre passos, amb **Open ID** al pas **Tipus**: + +| Pas | Camp | Significat | +|---|---|---| +| Detalls | Nom, Descripció | Un nom únic per al proveïdor i una descripció opcional | +| Tipus | Proveïdor | **Open ID**; es fixa quan es crea i no canvia | +| Credencials | Credencial | Una credencial **Open ID** de [Connexions > Credencials](../credentials.html), vegeu més avall | +| Grups | Filtre de grups | Expressió regular; només es conserven els valors del claim `groups` que coincideixen. Buit conserva tots els grups | + +La credencial conté el client, així que només un admin la pot afegir o canviar: + +| Camp | Significat | +|---|---| +| Emissor | Obligatori. La URL de l'emissor, p. ex. `https://keycloak.example.com/realms/example` | +| ID del client | L'ID de client al proveïdor, p. ex. `ansibleforms` | +| Secret del client | El secret de client, desat xifrat o llegit d'un [magatzem de secrets](../secret-stores/) | +| URI de redirecció | Tal com està registrat, p. ex. `https://af.example.com/api/v2/auth/oidc/callback`. Buit: la URL de l'aplicació i el camí de retorn | + +Fins a la 7.2.0 l'emissor, l'ID del client, el secret i la URL de redirecció eren camps del proveïdor. L'actualització a la 7.3.0 els trasllada a una +credencial anomenada `-sso`, vegeu [Adreces a les credencials](../credentials/types.html#addresses-in-credentials). +Tria una credencial per a cada proveïdor nou: el servidor encara accepta un proveïdor amb el seu propi ID de client i secret d'abans +de la 7.3.0, que hi inicia sessió fins que es tria una credencial. + +Només hi ha un proveïdor OIDC activat alhora, aquell amb què inicia sessió el botó d'OpenID. **Activa** al menú de fila d'un altre, +o el seu interruptor **Activat**, desactiva els altres del seu tipus; la columna **Activat** de la llista mostra quin s'està fent servir. +Un proveïdor també es pot saltar la pàgina d'inici de sessió, vegeu [Activar i desactivar l'inici de sessió únic](./#switching-single-sign-on). + +Desar el proveïdor l'aplica immediatament. Quan no es pot arribar a l'emissor, el servidor registra +`Failed to initialize OIDC strategy` i els inicis de sessió OIDC fallen fins que es torna a desar el proveïdor o es reinicia el servidor. + +--- + +## Assignació a rols + +A config.yaml, un grup OIDC és `oidc/` i un usuari és `oidc/`: + +```yaml +roles: + - name: admin + groups: + - local/admins + - oidc/af-admins + - name: operator + groups: + - oidc/af-operators + users: + - oidc/jdoe +``` + +Els valors es comparen exactament, majúscules i minúscules incloses. Vegeu [Rols](../config/roles.html) per a les opcions dels rols. + +--- + +## Limitacions + +Els usuaris OIDC inicien sessió al proveïdor, així que algunes coses funcionen de manera diferent que amb els comptes locals i LDAP: + +- No tenen contrasenya a AnsibleForms, així que no la hi poden canviar; des de la 7.2.0 un [token d'API](../profile/api-token.html) + es crea des de la seva sessió. +- Mantén curt el claim `groups`: envia només els grups que importen a AnsibleForms, per exemple amb un client scope dedicat + o una estructura de grups al proveïdor, o filtra'ls amb el **Filtre de grups**. Des de la 7.1.0 el token d'inici + de sessió d'AnsibleForms ja no porta els grups; abans, un usuari amb cent grups o més podia no veure cap formulari, vegeu + [Formularis i tasques buits després d'un inici de sessió únic](../troubleshooting.html#empty-forms-and-jobs-after-a-single-sign-on-http-431). diff --git a/i18n/ca/_configure/config/categories.md b/i18n/ca/_configure/config/categories.md new file mode 100644 index 0000000..4c32244 --- /dev/null +++ b/i18n/ca/_configure/config/categories.md @@ -0,0 +1,32 @@ +--- +layout: default +title: Categories +parent: config.yaml +nav_order: 1 +translated_from: b85b1c12cd01bdbdaa81c2de4ea9d91dac269e2f +--- + +# Categories +{: .no_toc } + +Agrupa els formularis al tauler. +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +## L'atribut categories + +La llista `categories` de primer nivell de config.yaml: + +{% include config_attribute.html name="categories" %} + +--- + +## Objecte Category + +Cada entrada de la llista `categories`: + +{% include config_object.html name="Category" %} diff --git a/i18n/ca/_configure/config/constants.md b/i18n/ca/_configure/config/constants.md new file mode 100644 index 0000000..812cb8a --- /dev/null +++ b/i18n/ca/_configure/config/constants.md @@ -0,0 +1,21 @@ +--- +layout: default +title: Constants +parent: config.yaml +nav_order: 3 +translated_from: 094e6c6c46990b88d06d0f6b1ae8e066b1912e57 +--- + +# Constants +{: .no_toc } + +Objectes lliures que tots els formularis poden reutilitzar. +{: .fs-6 .fw-300 } + +--- + +## L'atribut constants + +L'objecte `constants` de primer nivell de config.yaml: + +{% include config_attribute.html name="constants" %} diff --git a/i18n/ca/_configure/config/index.md b/i18n/ca/_configure/config/index.md new file mode 100644 index 0000000..b20f545 --- /dev/null +++ b/i18n/ca/_configure/config/index.md @@ -0,0 +1,73 @@ +--- +layout: default +title: config.yaml +nav_order: 5 +has_children: true +has_toc: false +permalink: /config/ +translated_from: 6c0e2d282bc1dc386b7392e3af1f60fea593f12b +--- + +# config.yaml +{: .no_toc } + +Categories, rols i constants per a tots els formularis +{: .fs-6 .fw-300 } + +--- + +Per a administradors: el fitxer config.yaml que conté les categories, els rols i les constants que comparteixen tots els formularis. + +AnsibleForms utilitza un fitxer config.yaml per configurar categories, rols i constants. Si no se n'hi proporciona cap, se'n genera un amb una configuració mínima. La configuració també es pot importar a la base de dades, i llavors ja no cal cap fitxer config.yaml. + +--- + +## Visió general + +El fitxer config.yaml conté la configuració de les categories, els rols i les constants que utilitza AnsibleForms. + +**VÍDEO**: [Crea el teu primer formulari](https://www.youtube.com/watch?v=lIhYZ9Et5Ic) + +El config.yaml mínim següent serveix com a punt de partida. Només conté la categoria obligatòria `Default` i els rols obligatoris `admin` i `default`. + +```yaml +categories: # a list of categories to group forms + - name: Default + icon: bars +roles: # a list of roles + - name: admin + groups: + - local/admins + - name: default + groups: [] + options: + allowJobRelaunch: true +constants: {} # free objects to re-use over all forms +``` + +--- + +## Prioritat de càrrega de la configuració + +AnsibleForms carrega el fitxer config.yaml en l'ordre següent (guanya la primera coincidència): + +1. **DES DE LA BASE DE DADES** : la configuració importada a la base de dades, només quan `ENABLE_CONFIG_IN_DATABASE=1`, o quan aquesta + variable no està definida i l'origen de configuració desat a la base de dades és `database` (una còpia buida recorre al fitxer) +2. **DES D'UN REPOSITORI (use_for_config)** : el repositori amb l'interruptor "utilitzar per a la configuració" activat (nou a la 6.1.0) +3. **DES D'UN REPOSITORI (use_for_forms)** : el repositori amb l'interruptor "utilitzar per als formularis" activat (alternativa per compatibilitat amb versions anteriors) +4. **DES D'UN FITXER LOCAL** : el fitxer local `config.yaml` (variable d'entorn CONFIG_PATH) + +{: .warning } +> **Nota:** Activa "utilitzar per a la configuració" en un sol repositori. Si n'hi ha diversos que el tenen activat, es registra un avís i s'utilitza el primer. + +--- + +## En aquesta secció + +El fitxer té tres atributs de primer nivell, i cadascun té la seva pròpia pàgina: + +| Pàgina | Què hi trobaràs | +|---|---| +| [Categories](categories.html) | Agrupa els formularis del tauler en un arbre de categories amb icones | +| [Rols](roles.html) | Assigna usuaris i grups a rols, i defineix què pot fer cada rol | +| [Constants](constants.html) | Objectes lliures que tots els formularis poden reutilitzar | diff --git a/i18n/ca/_configure/config/roles.md b/i18n/ca/_configure/config/roles.md new file mode 100644 index 0000000..c05cce2 --- /dev/null +++ b/i18n/ca/_configure/config/roles.md @@ -0,0 +1,125 @@ +--- +layout: default +title: Rols +parent: config.yaml +nav_order: 2 +translated_from: c23a8fb9203e85e81cd128d2c129228c0a207f6c +--- + +# Rols +{: .no_toc } + +Assigna usuaris i grups a rols, i defineix què pot fer cada rol. +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +## L'atribut roles + +La llista `roles` de primer nivell de config.yaml: + +{% include config_attribute.html name="roles" %} + +--- + +## El rol default + +Tots els usuaris que han iniciat sessió tenen el rol `default`, de manera que un formulari amb `roles: [default]` està obert a tothom qui pot iniciar sessió. No +hi ha accés anònim: ningú no rep aquest rol sense iniciar sessió. + +El rol no conté cap grup ni cap usuari, perquè ja s'aplica a tothom. Les seves `options` són els valors predeterminats de tothom, tal com +es descriu a [Opcions de rol](#role-options) més avall. `config.yaml` ha de tenir un rol `admin` i un rol `default`, i la +pàgina de rols mostra tots dos com a **Obligatori**. + +`default` es deia `public` abans de la 7.0.0, i el nom antic continua funcionant: + +- **En un formulari**, `roles: [public]` continua coincidint amb tots els usuaris, així que els formularis dels teus repositoris no necessiten cap canvi. +- **A `config.yaml`**, un rol anomenat `public` es reanomena `default` al fitxer quan es carrega la configuració. Només canvia el + nom, abans es fa una còpia de seguretat de la configuració, i una configuració guardada en un repositori queda amb un canvi pendent de fer push. +- **En una plantilla ytt**, la plantilla no es reescriu: es reanomena la configuració que produeix, i un avís al registre et demana + que també reanomenis el rol a la plantilla. La versió 8 hi rebutja un rol `public`. + +Una configuració que té alhora un rol `default` i un rol `public` es rebutja, perquè són el mateix rol. + +--- + +## Objecte Role + +Cada entrada de la llista `roles`: + +{% include config_object.html name="Role" %} + +--- + +## Opcions de rol + +Les `options` d'un rol activen o desactiven funcions per als seus membres. Des de la 7.3.0 la pàgina del rol les mostra en quatre grups, +cada opció amb una (i) que explica què dona, el mateix text que mostra la vista **Permisos** del perfil: + +| Opció | Permet a l'usuari | Predeterminat | +|---|---|---| +| **Configuració** | | | +| `showSettings` | Veure i canviar totes les pàgines de configuració; el registre del servidor i les còpies de seguretat tenen les seves pròpies opcions | Només admins | +| `showAppearanceSettings` | Canviar la configuració d'aparença, sense la resta de la configuració (des de la 7.3.0) | Desactivat | +| `showConnectionsSettings` | Gestionar la configuració de connexions (credencials, runners i més), sense la resta de la configuració (des de la 7.3.0) | Desactivat | +| `showLogs` | Veure el registre del servidor | Només admins | +| `showAuditLog` | Veure el registre d'auditoria, sense la resta de la configuració (des de la 7.3.0) | Només admins | +| `allowBackupOps` | Fer còpies de seguretat de la base de dades i restaurar-la | Només admins | +| **Dissenyador** | | | +| `showDesigner` | Veure i utilitzar el dissenyador | Només admins | +| `allowFormDesign` | Editar la configuració de formularis al dissenyador: categories, constants i formularis. Sense aquesta opció, només lectura (des de la 7.3.0) | Activat | +| `allowPlaybookDesign` | Editar els playbooks al dissenyador: desar-los, crear-los, treure'ls i fer-ne push. Sense aquesta opció, només lectura | Activat | +| `allowWorkflowDesign` | Editar els workflows al dissenyador: desar-los, crear-los, treure'ls i fer-ne push. Sense aquesta opció, només lectura | Activat | +| `allowInventoryDesign` | Editar els inventaris al dissenyador: desar-los, crear-los, treure'ls i fer-ne push. Sense aquesta opció, només lectura | Activat | +| `allowVarsFileDesign` | Editar els fitxers de variables al dissenyador: desar-los, crear-los, treure'ls i fer-ne push. Sense aquesta opció, només lectura | Activat | +| **Tasques** | | | +| `showJobs` | Veure la pàgina de tasques | Activat | +| `showAllJobLogs` | Veure les tasques de tots els usuaris, no només les seves | Només admins | +| `manageAllJobs` | Avortar, suprimir i tornar a llançar les tasques de tots els usuaris; suprimir i tornar a llançar també necessiten les dues opcions següents (des de la 7.3.0) | Només admins | +| `showExtravars` | Veure les extravars d'un formulari i d'una tasca | Activat | +| `showDebugButtons` | Veure els botons de depuració d'un formulari | Activat | +| `showArtifacts` | Veure els artefactes d'una tasca: el que retorna una tasca d'AWX, o el que un playbook ha recollit amb `set_stats` | Activat | +| `allowVerboseMode` | Executar tasques en mode detallat | Activat | +| `allowJobRelaunch` | Tornar a llançar una tasca amb les dades del formulari d'una execució anterior | Només admins | +| `allowJobDeletion` | Suprimir tasques: les seves, o les de tots els usuaris amb `manageAllJobs`. Sense aquesta opció, l'historial de tasques es conserva sencer (des de la 7.3.0) | Activat | +| `allowScheduledJobs` | Crear i gestionar programacions recurrents i puntuals, a la pàgina **Programacions** (vegeu l'avís més avall) | Només admins | +| `allowPlannedJobs` | Planificar una tasca perquè s'executi una vegada a una hora fixada (**Executa més tard**) | Activat | +| `allowStoredJobs` | Desar les dades d'un formulari i tornar-les a carregar més tard | Activat | +| **Accés i integracions** | | | +| `allowLogin` | Iniciar sessió a AnsibleForms | Activat | +| `allowChat` | Utilitzar l'[assistent de xat](../chat/), quan està activat | Activat | +| `allowMcp` | Utilitzar el [servidor MCP](../mcp/) des d'un agent d'IA, quan està activat | L'`allowChat` del rol | +| `allowFileUploads` | Pujar fitxers mitjançant els camps de fitxer d'un formulari (des de la 7.3.0) | Activat | +| `allowApiTokens` | Crear [tokens d'API](../profile/api-token.html) per a scripts, fins a la durada màxima que permet la instància (des de la 7.3.0) | Desactivat | +| `extendedTokenExpiration` | Crear també tokens d'API que no caduquen mai; necessita `allowApiTokens` | Desactivat | + +Algunes opcions n'inclouen d'altres, i la pàgina del rol mostra les incloses activades i en gris: + +- **`showSettings`** també dona `showAppearanceSettings`, `showConnectionsSettings` i `showAuditLog`. +- **`manageAllJobs`** també dona `showAllJobLogs`, ja que actuar sobre les tasques de tots els usuaris vol dir veure-les. +- **Les opcions de disseny** només compten amb `showDesigner`, i `extendedTokenExpiration` només amb `allowApiTokens`. + +Fins a la 7.2.0, `showAllJobLogs` també permetia a l'usuari avortar i suprimir les tasques que mostrava; des de la 7.3.0 això requereix `manageAllJobs`. +Un rol d'abans de la 7.3.0 amb `extendedTokenExpiration` i sense `allowApiTokens` rep `allowApiTokens`, de manera que conserva els seus tokens. + +**Només admins** vol dir activat per als usuaris que tenen el rol `admin`, i desactivat per a tota la resta. Quan un usuari coincideix amb diversos rols, +les opcions es combinen així: + +- **Entre els rols de l'usuari**, una opció només està activada quan tots els rols que la defineixen hi estan d'acord: un `false` explícit guanya. +- **El rol `default`** completa les opcions que no defineix cap dels altres rols de l'usuari, de manera que pot contenir valors predeterminats per a tothom. +- **Les opcions que no es defineixen enlloc** prenen el valor predeterminat de la taula. + +`showExtraVars`, amb V majúscula, s'accepta com una altra grafia de `showExtravars`; quan qualsevol de les dues és `false`, l'opció +està desactivada. + +{: .warning } +> Tracta `allowScheduledJobs` com una opció de nivell d'admin. Les programacions no pertanyen a l'usuari que les ha creat: tots els usuaris amb +> l'opció veuen i poden canviar totes les programacions. A més, una programació s'executa amb drets d'admin, per a qualsevol formulari, sigui quin sigui +> l'accés del creador. Concedeix-la només a rols en què confiaries com a admins. + +{: .warning } +> `allowLogin: false` al rol `default` deixa fora tots els usuaris els altres rols dels quals no defineixen `allowLogin: true`, inclosos +> els admins. Torna-la a concedir als rols que han de poder iniciar sessió abans de desar. diff --git a/i18n/ca/_configure/credentials.md b/i18n/ca/_configure/credentials.md new file mode 100644 index 0000000..3d0c6ea --- /dev/null +++ b/i18n/ca/_configure/credentials.md @@ -0,0 +1,74 @@ +--- +layout: default +title: Credencials +nav_order: 6 +has_children: true +has_toc: false +permalink: /credentials.html +translated_from: 08110077a1cf59a4a52e078fc2ebc252f7cae48d +--- + +# Credencials +{: .no_toc } + +Desa els accessos amb què es connecten els formularis, els repositoris, els magatzems de secrets i els canals de notificació +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +Per a administradors: afegeix els usuaris, les contrasenyes i els tokens amb què es connecta AnsibleForms, desats xifrats o llegits d'un magatzem de secrets. + +--- + +## En aquesta secció + +| Pàgina | Què hi trobaràs | +|---|---| +| [Tipus de credencial](credentials/types.html) | Què conté cada tipus i on es pot triar | +| [La pàgina de credencials](credentials/list.html) | La llista de credencials i el diàleg que n'afegeix una | +| [La pàgina d'una credencial](credentials/credential-page.html) | Les pestanyes d'una credencial i què la utilitza | + +--- + +## Com funciona + +Una **credencial** és un accés amb nom, que s'afegeix a **Connexions > Credencials**. Els formularis i els altres objectes d'administració +s'hi refereixen pel seu nom, de manera que la contrasenya mai no apareix en un formulari. El seu usuari i la seva contrasenya o bé es desen a la +base de dades d'AnsibleForms, xifrats amb `ENCRYPTION_SECRET`, o bé es llegeixen d'un [magatzem de secrets](secret-stores/) cada vegada que +s'utilitza la credencial. + +--- + +## Qui pot canviar una credencial + +Des de la 7.3.0, una credencial de la qual depèn una connexió o un inici de sessió només la pot afegir, canviar o suprimir un admin: + +| Credencials | Per què | +|---|---| +| Tipus de connexió: `rte`, `awx`, `aap`, `ascender`, `semaphore`, `rundeck`, `jenkins`, `vault` i `cyberark` | Un runner o un magatzem de secrets en pren l'adreça i el secret | +| Tipus d'inici de sessió: `oidc`, `entraid` i `ldap` | Un proveïdor SSO o un directori LDAP hi inicia la sessió dels usuaris | +| Qualsevol credencial que nomeni un runner | El runner hi inicia sessió, i un canvi del mateix runner també necessita un admin | + +Els altres usuaris amb accés a les credencials les veuen només de lectura. Un usuari que pogués apuntar una credencial d'aquest tipus a un altre +servidor rebria tots els secrets que s'hi envien, i per això la regla segueix la dels runners. Tres regles més +mantenen aquests usuaris lluny de secrets que d'una altra manera no podrien llegir: + +- **Nomenar una credencial protegida**: només un admin pot nomenar una d'aquestes credencials en un altre lloc, com ara en un repositori, + un canal de notificació o la configuració de l'assistent de xat. Una credencial que llegeix la seva contrasenya d'un magatzem de secrets està + protegida de la mateixa manera, sigui quin sigui el seu tipus. +- **Triar un magatzem de secrets**: només un admin pot apuntar una credencial a un [magatzem de secrets](secret-stores/), o canviar el + magatzem o la referència que llegeix; un altre usuari encara els pot tornar a enviar sense canvis, o buidar-los tots. +- **Moure una credencial**: quan un altre usuari canvia on inicia sessió una credencial (el seu host, port, emissor, tenant o + adreça del servidor) sense tornar a escriure'n la contrasenya, la contrasenya desada s'esborra, i també la referència del magatzem de secrets + que llegeix, de manera que el secret antic mai no va al nou destí. + +--- + +## Credencials en ús + +Una credencial que encara nomenen altres registres no es pot suprimir ni reanomenar, perquè quedarien apuntant a res. +El rebuig indica quants registres la utilitzen; la pestanya **Usat per** de [la seva pàgina](credentials/credential-page.html) els llista. +Apunta'ls primer a una altra credencial, i després suprimeix-la o reanomena-la. diff --git a/i18n/ca/_configure/credentials/credential-page.md b/i18n/ca/_configure/credentials/credential-page.md new file mode 100644 index 0000000..5f4ba79 --- /dev/null +++ b/i18n/ca/_configure/credentials/credential-page.md @@ -0,0 +1,31 @@ +--- +layout: default +title: "La pàgina d'una credencial" +parent: Credencials +nav_order: 3 +translated_from: 0269b5c0d313622bea6c910b96231f41ffd852d7 +--- + +# La pàgina d'una credencial +{: .no_toc } + +Les pestanyes d'una credencial i què la utilitza +{: .fs-6 .fw-300 } + +La pàgina d'una credencial mostra els passos del seu diàleg com a pestanyes, més el que la utilitza: + +| Pestanya | Què conté | +|---|---| +| Detalls | Nom i descripció. | +| Tipus | Per a què serveix la credencial. | +| Accés | Tots els camps del seu tipus, com al pas **Accés** del diàleg: l'usuari, la contrasenya i on inicia sessió (host i port, la base de dades, el servidor de correu, els servidors del directori, el tenant o l'emissor, l'adreça del servidor i el seu TLS). L'AppID, el certificat de client i la clau d'una credencial CyberArk. | +| Magatzem | Base de dades o Magatzem de secrets, i el magatzem i la referència. No per a CyberArk ni HashiCorp Vault. | +| Usat per | Tot el que nomena aquesta credencial: magatzems de secrets, canals de notificació, repositoris, directoris LDAP, proveïdors SSO, runners, l'assistent de xat, formularis i els workflows del dissenyador. Una fila l'obre. | + +La contrasenya s'escriu a la pestanya **Accés** i no es torna a mostrar mai un cop desada: si es deixa buida, es conserva la desada. En una credencial +CyberArk, deixa buida la clau de client per conservar la desada. A dalt a la dreta hi ha **Prova la connexió** (només credencials de base de dades), +**Suprimeix** i **Desa**. + +Des de la 7.3.0, **Suprimeix** i un nom nou es rebutgen mentre **Usat per** llisti alguna cosa, vegeu [Credencials en ús](../credentials.html#credentials-in-use). + +Una credencial declarada a la [llavor de configuració](../seed/) és només de lectura en aquesta pàgina: canvia-la al fitxer de la llavor. diff --git a/i18n/ca/_configure/credentials/list.md b/i18n/ca/_configure/credentials/list.md new file mode 100644 index 0000000..7ddd28f --- /dev/null +++ b/i18n/ca/_configure/credentials/list.md @@ -0,0 +1,45 @@ +--- +layout: default +title: La pàgina de credencials +parent: Credencials +nav_order: 2 +translated_from: 986d768c15d0b91bdc3760026bd904d3f89ff3e0 +--- + +# La pàgina de credencials +{: .no_toc } + +La llista de credencials i el diàleg que n'afegeix una +{: .fs-6 .fw-300 } + +La pàgina de **Connexions > Credencials** llista totes les credencials amb el seu **Nom**, **Tipus**, **Descripció** i **Usat per**, el +nombre de registres, formularis i workflows que la nomenen (vegeu [Credencials en ús](../credentials.html#credentials-in-use)). + +**Afegeix credencial** obre un diàleg per passos: + +| Pas | Camps | +|---|---| +| Credencial | Nom i descripció, tots dos obligatoris. | +| Tipus | Un de 18 tipus, vegeu més avall. | +| Accés | Amb què i on inicia sessió el tipus, vegeu més avall. | +| Magatzem | On es desen l'usuari i la contrasenya: **Base de dades** (xifrats a la base de dades d'AnsibleForms) o **Magatzem de secrets**, amb el magatzem i la **Referència** que hi ha dins. No per a CyberArk ni HashiCorp Vault, amb els quals inicia sessió un magatzem de secrets. | + +El pas **Tipus** llista els tipus pel seu nom: AAP, API, Ascender, AWX, CyberArk, Base de dades, Git, HashiCorp Vault, Jenkins, LDAP, +Microsoft Entra ID, Open ID, RTE, Rundeck, Semaphore, SMTP, SSH i Usuari i contrasenya (vegeu [Tipus de credencial](types.html)). + +El pas **Accés** conté tots els camps del tipus, l'adreça inclosa; no hi ha cap pas de connexió a part: + +| Tipus | Camps del pas Accés | +|---|---| +| Tots els tipus excepte CyberArk | La contrasenya, o el que en fa les funcions: la contrasenya de bind de LDAP, el secret de client d'Entra ID i Open ID, el token d'HashiCorp Vault, el token de l'RTE, el token d'API de Semaphore, Rundeck i Jenkins, un token o una contrasenya per a AWX, AAP i Ascender | +| Tots els tipus excepte HashiCorp Vault, RTE, Semaphore i Rundeck | L'usuari: l'AppID de CyberArk, el DN de bind de LDAP, l'ID de client d'Entra ID i Open ID, opcional per a AWX, AAP i Ascender | +| SSH, Base de dades | **Amfitrió** i **Port**; per a una base de dades també el **Tipus de base de dades** i la **Base de dades** | +| SMTP | **Servidor de correu** (obligatori), el seu **Port** i **Utilitza TLS** | +| LDAP | Els **Servidors** del directori (obligatori), el seu **Port** i **Activa TLS**; amb TLS, **Ignora els certificats**, el **Paquet de CA** i un **Certificat de client** | +| Microsoft Entra ID | **ID del tenant** (obligatori) i **URI de redirecció** | +| Open ID | **Emissor** (obligatori) i **URI de redirecció** | +| HashiCorp Vault, CyberArk, RTE, AWX, AAP, Ascender, Semaphore, Rundeck, Jenkins | **Servidor**, l'adreça on inicia sessió, obligatori, amb **Omet la verificació del certificat** i el **Paquet de CA** | +| CyberArk | **Certificat de client** i **Clau del client** | + +Una fila obre la pàgina pròpia de la credencial. El seu menú ofereix **Edita**, **Prova la connexió** (només credencials de base de dades) i **Suprimeix**. La +contrasenya es canvia a la pàgina de la credencial, a la seva pestanya **Accés**. diff --git a/i18n/ca/_configure/credentials/types.md b/i18n/ca/_configure/credentials/types.md new file mode 100644 index 0000000..1d55ca2 --- /dev/null +++ b/i18n/ca/_configure/credentials/types.md @@ -0,0 +1,65 @@ +--- +layout: default +title: Tipus de credencial +parent: Credencials +nav_order: 1 +translated_from: 1f21f8fc1ae73953922d8c9f21de6db05b3b1a87 +--- + +# Tipus de credencial +{: .no_toc } + +Què conté cada tipus i on es pot triar +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +## Els tipus + +El tipus indica per a què serveix una credencial. Decideix quins camps demana el diàleg i on es pot triar: + +| Tipus | Què conté | Usat per | +|---|---|---| +| Usuari i contrasenya | Un usuari i una contrasenya per a qualsevol accés: una API REST amb autenticació bàsica, un servei i més. El predeterminat | Playbooks, mitjançant les `credentials` d'un formulari o un camp de credencial; [expressions REST](../expressions/credentials.html) | +| SSH | Un usuari i una contrasenya per a SSH a un servidor, amb el seu host i el seu port | Playbooks, mitjançant les `credentials` o `ansibleCredentials` d'un formulari o un camp de credencial, i l'accés d'un node de workflow | +| Git | Un usuari i una contrasenya o un token per a repositoris git | [Repositoris](../repositories/authentication.html) | +| API | Un usuari i una contrasenya o un token per a una API REST | [Expressions REST](../expressions/credentials.html), el token d'un bot de Telegram, el bearer token d'un webhook, la clau d'API de l'assistent de xat | +| Base de dades | Un accés a base de dades, amb el seu tipus, host, port i nom de base de dades | Consultes de formularis (`dbConfig`) i `fnCredentials`; es pot provar | +| CyberArk | L'adreça del CyberArk Central Credential Provider (CCP) i el seu TLS, i l'AppID, el certificat de client i la clau amb què accedeix un magatzem CyberArk | Un magatzem de secrets [CyberArk](../secret-stores/cyberark.html) | +| SMTP | Un servidor de correu, el seu port i TLS, i el seu accés (cap per a un relay) | Un [canal de notificació](../notification-channels.html) de correu | +| LDAP | Els servidors, el port, el TLS i els certificats d'un directori, i el seu DN i contrasenya de bind | Un [directori LDAP](../authentication/ldap.html) | +| Microsoft Entra ID | El registre d'aplicació d'un proveïdor: el seu ID de tenant, ID de client, secret de client i URI de redirecció | Un [proveïdor Entra ID](../authentication/entra-id.html) | +| Open ID | El client d'un proveïdor: el seu emissor, ID de client, secret de client i URI de redirecció | Un [proveïdor OIDC](../authentication/oidc.html) | +| RTE | El token (`RTE_TOKEN`) i l'adreça d'un RTE | Un [runner](../runners.html) RTE | +| AWX, AAP, Ascender | El token o l'accés, i l'adreça, d'aquesta plataforma | Un runner d'aquest tipus | +| Semaphore, Rundeck | El token d'API i l'adreça d'aquest producte | Un runner d'aquest tipus | +| Jenkins | Un usuari, el seu token d'API i l'adreça d'un Jenkins | Un runner Jenkins | +| HashiCorp Vault | El token i l'adreça amb què accedeix un magatzem Vault | Un magatzem de secrets [HashiCorp Vault](../secret-stores/hashicorp-vault.html) | + +Una credencial de base de dades pot ser de tipus MySQL, MSSQL, PostgreSQL, Oracle o MongoDB. + +A l'API i a la [llavor de configuració](../seed/), els tipus són `userpass`, `ssh`, `git`, `api`, `database`, `cyberark`, `smtp`, +`ldap`, `entraid`, `oidc`, `rte`, `awx`, `aap`, `ascender`, `semaphore`, `rundeck`, `jenkins` i `vault`. L'actualització des de la 6 +dona a cada credencial el tipus `userpass`, o `database` a una de base de dades: un formulari la utilitza com a la 6. Canvia-la a SSH per a un +accés amb què es connecta el playbook d'un node de workflow, o a API per a una API REST. + +--- + +## Adreces a les credencials + +Des de la 7.3.0, un accés que funciona en un servidor porta amb si aquest servidor, de manera que el registre que l'utilitza només nomena la credencial: + +| Registre | Què ha passat a la seva credencial | +|---|---| +| Un directori LDAP | Els seus servidors, port, TLS, certificats i compte de bind, a una credencial `ldap` anomenada `-ldap` | +| Un proveïdor SSO | El seu ID de client i secret, tenant o emissor, i URI de redirecció, a una credencial `entraid` o `oidc` anomenada `-sso` | +| Un runner | La seva adreça i TLS, i el seu token o accés, a una credencial del seu tipus, `-token` o `-login` | +| Un magatzem de secrets | La seva adreça i TLS, i el seu token (`-token`) o l'AppID i el certificat de CyberArk (`-appid`) | +| Un canal de correu | El seu servidor, port i TLS, a la seva credencial `smtp`, o a una de nova anomenada `-smtp` | + +L'actualització a la 7.3.0 fa aquests trasllats una sola vegada. Un registre que ja nomenava una credencial la conserva, i en rep una còpia quan +un altre registre utilitzava el mateix accés amb un altre servidor. Els registres declarats a la [llavor de configuració](../seed/) es deixen tal com els té la llavor. +Les credencials de les connexions i dels inicis de sessió només les pot canviar un admin, vegeu [Qui pot canviar una credencial](../credentials.html#who-may-change-a-credential). diff --git a/i18n/ca/_configure/customization/configuration.md b/i18n/ca/_configure/customization/configuration.md new file mode 100644 index 0000000..e65a380 --- /dev/null +++ b/i18n/ca/_configure/customization/configuration.md @@ -0,0 +1,62 @@ +--- +layout: default +title: Configuració +parent: Variables d'entorn +nav_order: 5 +translated_from: f460336cad995f3fd6cb5a2e4667e4c1a3b67a2b +--- + +# Configuració +{: .no_toc } + +La llavor de configuració, on es desa la configuració, git i ytt +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +Canvia aquestes variables per decidir d'on surt la configuració: una llavor de configuració, la base de dades, git o plantilles ytt. + +--- + +## Exemple + +Aplica una llavor de configuració muntada, comprova-la cada cinc minuts i desa `config.yaml` a la base de dades. A `docker-compose.yml`: + +```yaml + environment: + - CONFIG_SEED_PATH=/seed/seed.yaml + - CONFIG_SEED_RELOAD_SECONDS=300 + - ENABLE_CONFIG_IN_DATABASE=1 + - ALLOW_ENV_EDIT=0 # the environment is declared here, not on the settings pages + volumes: + - ./seed:/seed:ro +``` + +Una llavor no vàlida impedeix que el servidor arrenqui. Vegeu [Llavor de configuració](../seed/) per al format del fitxer. + +--- + +## D'on es llegeix config.yaml + +Les categories, els rols i les constants surten de `config.yaml` al disc o de la seva còpia a la base de dades, decidit en aquest ordre: + +1. [`ENABLE_CONFIG_IN_DATABASE`](#env_ENABLE_CONFIG_IN_DATABASE), quan està definida, a l'entorn o a la + pestanya **Configuració** de la pàgina de configuració: `1` llegeix la base de dades, `0` llegeix el fitxer. +2. Si no, l'origen de configuració desat a la base de dades (`file` o `database`), que les instàncies configurades + abans de la 6.3.0 van triar a la pàgina de configuració. +3. Si no, el fitxer: el `config.yaml` del repositori amb **Utilitzar per a la configuració ?** activat, si no el d'un repositori amb + **Utilitzar per als formularis ?** activat, i si no el de [`CONFIG_PATH`](paths.html#env_CONFIG_PATH). + +Un `ENABLE_CONFIG_IN_DATABASE` definit explícitament sempre guanya, fins i tot `0` davant d'un `database` desat. Es llegeix cada vegada que +es carrega la configuració, així que un canvi s'aplica sense reiniciar. La pàgina **Estat** mostra l'origen en ús a la seva pestanya **Informació**. + +--- + +## Variables + +Totes les variables d'aquest grup, amb el seu tipus, el seu valor predeterminat i la seva descripció: + +{% include env_vars_table.html group="configuration" %} diff --git a/i18n/ca/_configure/customization/features.md b/i18n/ca/_configure/customization/features.md new file mode 100644 index 0000000..83f5d98 --- /dev/null +++ b/i18n/ca/_configure/customization/features.md @@ -0,0 +1,45 @@ +--- +layout: default +title: Funcions +parent: Variables d'entorn +nav_order: 4 +translated_from: dbd2d865ae9b177e389409777bdfffc8f199f9da +--- + +# Funcions +{: .no_toc } + +El dissenyador, MCP, el xat, la validació del llançament, la llista de tasques, les mètriques, l'API d'AWX i el registre de consultes +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +Canvia aquestes variables per activar o desactivar parts opcionals de l'aplicació. + +--- + +## Exemple + +Serveix el servidor MCP per a agents d'IA i imposa les regles de validació del formulari a cada llançament. Al `.env` del projecte compose: + +```bash +ENABLE_MCP=1 +LAUNCH_VALIDATION=enforce +``` + +`ENABLE_MCP` i `ENABLE_CHAT` s'apliquen sense reiniciar: es llegeixen a cada petició, així que les pots activar a la +pàgina de configuració. Mentre una està desactivada, el seu endpoint (`/api/v2/mcp` o `/api/v2/chat`) respon `404`. + +Executa primer `LAUNCH_VALIDATION=log` durant un temps: registra el que `enforce` rebutjaria, sense rebutjar-ho. Vegeu [MCP](../mcp/) +i [Registrar i imposar](../launch-validation/log-and-enforce.html). + +--- + +## Variables + +Totes les variables d'aquest grup, amb el seu tipus, el seu valor predeterminat i la seva descripció: + +{% include env_vars_table.html group="features" %} diff --git a/i18n/ca/_configure/customization/index.md b/i18n/ca/_configure/customization/index.md new file mode 100644 index 0000000..14205d5 --- /dev/null +++ b/i18n/ca/_configure/customization/index.md @@ -0,0 +1,81 @@ +--- +layout: default +title: Variables d'entorn +nav_order: 8 +has_children: true +has_toc: false +permalink: /customization/ +translated_from: fd6e83f3550f59aa576c8addaf28bfa6115b96a0 +--- + +# Variables d'entorn +{: .no_toc } + +Configura AnsibleForms amb variables d'entorn +{: .fs-6 .fw-300 } + +--- + +Per a administradors que despleguen AnsibleForms: les variables d'entorn que llegeix el servidor, agrupades per tema. + +AnsibleForms s'ajusta amb variables d'entorn, tant si s'executa amb Docker Compose, a Kubernetes o des del codi font. + +--- + +## D'on surten els valors + +El servidor llegeix cada variable de la primera d'aquestes fonts que la defineix, així que un valor més amunt a la llista sempre guanya: + +1. **L'entorn del procés**: `environment:` i `env_file:` a docker-compose (el `.env` del projecte es passa així), + `env` i `envFrom` a Kubernetes, o la shell que arrenca `node`. +2. **`persistent/.env`**, el fitxer que escriuen les pàgines de configuració (`data/.env` al projecte docker-compose, un altre camí amb + `MANAGED_ENV_PATH`). Es llegeix a cada arrencada, també en producció, i mai no sobreescriu una variable que ja està definida. +3. **`server/.env.`**, per exemple `.env.development`. Només es llegeix quan `NODE_ENV` no és `production` (o amb + `FORCE_DOTENV=1`), a la pràctica quan s'executa [des del codi font](../installation/from-source.html) en mode de desenvolupament. +4. **El valor predeterminat integrat**, que apareix a les taules de cada grup. + +Les pàgines de configuració, a **Configuració > General**, mostren el valor vigent i desen els canvis a `persistent/.env`. Moltes variables +s'apliquen tan bon punt es desen; les altres es desen però necessiten un reinici, i la pàgina les llista després de desar. Una variable definida a +l'entorn del procés no s'hi pot canviar: la pàgina la mostra com a *Definit a l'entorn, així que no es pot canviar aquí.* +Algunes variables, com ara `ENCRYPTION_SECRET` i `ACCESS_TOKEN_SECRET`, no es poden canviar mai des de la pàgina. + +Les variables que llegeix un RTE, com ara `AF_ROLE`, `RTE_MODE`, `APP_URL` o `RTE_MAX_JOBS`, no són a les pàgines de configuració: l'aplicació +no les utilitza, així que defineix-les a l'entorn on s'executa l'RTE. Les variables `RTE_*` que llegeix la mateixa aplicació, +`RTE_QUEUE_MINUTES` i `RTE_FILES_MAX_MB`, són l'excepció i continuen a les pàgines. Quatre variables de l'RTE, `RTE_MAX_JOBS`, +`RTE_CACHE_MB`, `RTE_FILES` i `RTE_DRAIN_SECONDS`, es poden definir per a cada RTE a la seva pàgina de runner, on un valor guanya a la +variable (vegeu [La configuració d'un RTE](../runners/runner-page.html#an-rtes-settings)). + +Amb [`ALLOW_ENV_EDIT`](configuration.html#env_ALLOW_ENV_EDIT)`=0` les pàgines només mostren els valors i el desament es rebutja. Fes-lo servir +quan l'entorn es declara en un manifest, tal com es descriu a [Edició i auditoria](../seed/environment-and-audit.html). + +La [llavor de configuració](../seed/) no defineix cap variable d'entorn. Declara objectes que es desen a la base de dades, i les +referències `${ENV_VAR}` que conté es resolen a partir de l'entorn del servidor en execució. + +Algunes variables només es llegeixen de l'entorn i no són a les taules: `MANAGED_ENV_PATH` i `FORCE_DOTENV`, descrites +més amunt, i les variables de proxy del sistema `HTTPS_PROXY` i `NO_PROXY` (també es llegeixen en minúscules). Un RTE sortint truca a l'aplicació a través de +`HTTPS_PROXY`, i un RTE entrant hi envia la seva crida de registre, tret que el host de l'aplicació sigui a `NO_PROXY` (noms de host, +sufixos `.domain`, o `*` per a tots els hosts). + +Les variables marcades amb Secret contenen una contrasenya, un token o una clau: mantén-les fora del control +de versions, per exemple en un Secret de Kubernetes o en un fitxer `.env` que no es faci commit. + +--- + +## En aquesta secció + +Les variables s'agrupen per tema, amb una pàgina per grup: + +| Pàgina | Què hi trobaràs | +|---|---| +{% for g in site.data.env_groups %}| [{{ g.title }}]({{ g.slug }}.html) | {{ g.lead | slice: 0 | upcase }}{{ g.lead | slice: 1, 500 }} | +{% endfor %} +{% capture other %}{% include env_vars_table.html rest=true %}{% endcapture %} +{% if other contains "" %} +--- + +## Altres variables + +Les variables següents encara no estan assignades a cap grup: + +{{ other }} +{% endif %} diff --git a/i18n/ca/_configure/customization/logging.md b/i18n/ca/_configure/customization/logging.md new file mode 100644 index 0000000..c377565 --- /dev/null +++ b/i18n/ca/_configure/customization/logging.md @@ -0,0 +1,49 @@ +--- +layout: default +title: Registre +parent: Variables d'entorn +nav_order: 7 +translated_from: 81439c2c8adc69d31191b0a07cd9e444ff5fb2be +--- + +# Registre +{: .no_toc } + +Nivells de registre, fitxers, syslog i colors de la consola +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +Canvia aquestes variables per ajustar quant es registra, on van els fitxers de registre, o per mostrar les marques de temps a la teva pròpia zona horària. + +--- + +## Exemple + +Registra més als fitxers que a la consola, i mostra les marques de temps del registre i de les tasques en hora d'Amsterdam. +Al `.env` del projecte compose: + +```bash +LOG_LEVEL=info +LOG_CONSOLE_LEVEL=notice +LOG_TZ=Europe/Amsterdam +``` + +--- + +## Syslog + +Els servidors syslog ja no es configuren aquí: afegeix-los a **Configuració > Connexions > Syslog**, vegeu [Registres](../production/logs.html#syslog). +Les variables `LOG_SYSLOG_*` de sota estan obsoletes des de la 7. La primera arrencada que troba `LOG_SYSLOG_HOST` definida les importa +una sola vegada com el servidor syslog `syslog`, que rep el registre del servidor, i a partir d'aleshores les ignora. + +--- + +## Variables + +Totes les variables d'aquest grup, amb el seu tipus, el seu valor predeterminat i la seva descripció: + +{% include env_vars_table.html group="logging" %} diff --git a/i18n/ca/_configure/customization/paths.md b/i18n/ca/_configure/customization/paths.md new file mode 100644 index 0000000..e20b54a --- /dev/null +++ b/i18n/ca/_configure/customization/paths.md @@ -0,0 +1,45 @@ +--- +layout: default +title: Camins +parent: Variables d'entorn +nav_order: 2 +translated_from: 232fd91a41c511e9f46867101d74d2313dc7ee3c +--- + +# Camins +{: .no_toc } + +On són la configuració, els formularis, els playbooks, els fitxers pujats i les còpies de seguretat +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +Canvia aquestes variables per desar part de les dades en un altre volum, per exemple les còpies de seguretat i els fitxers pujats en un emmagatzematge més gran o més barat. + +--- + +## Exemple + +Còpies de seguretat i fitxers pujats en un volum a part, i la resta de les dades a la carpeta persistent habitual. A `docker-compose.yml`: + +```yaml + environment: + - BACKUP_PATH=/data/backups + - FORMS_BACKUP_PATH=/data/forms_backups + - UPLOAD_PATH=/data/uploads + volumes: + - /srv/ansibleforms-data:/data +``` + +Un camí nou només s'aplica als fitxers nous: el que ja és a la carpeta antiga no es mou, així que copia-ho tu mateix. + +--- + +## Variables + +Totes les variables d'aquest grup, amb el seu tipus, el seu valor predeterminat i la seva descripció: + +{% include env_vars_table.html group="paths" %} diff --git a/i18n/ca/_configure/customization/retention.md b/i18n/ca/_configure/customization/retention.md new file mode 100644 index 0000000..68c4c07 --- /dev/null +++ b/i18n/ca/_configure/customization/retention.md @@ -0,0 +1,42 @@ +--- +layout: default +title: Còpies de seguretat i retenció +parent: Variables d'entorn +nav_order: 3 +translated_from: 76f81cfa15eaa98199a3d5963f7adc9a6f8b01dc +--- + +# Còpies de seguretat i retenció +{: .no_toc } + +Les ordres de còpia de seguretat, i quant de temps es conserven les còpies, les tasques i els registres d'auditoria +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +Canvia aquestes variables per controlar quant d'historial conserva la base de dades i quantes còpies de seguretat es queden al disc. + +--- + +## Exemple + +Conserva les tasques acabades durant 90 dies i el rastre d'auditoria durant dos anys. Al `.env` del projecte compose: + +```bash +JOB_RETENTION_DAYS=90 +AUDIT_RETENTION_DAYS=730 +``` + +Una tasca diària elimina les tasques acabades més antigues que això a les 2:30 de la matinada i les entrades d'auditoria a les 3:30. Una tasca en execució, o una que espera +aprovació, no s'elimina mai. Totes dues variables s'apliquen sense reiniciar quan es canvien a la pàgina de configuració. + +--- + +## Variables + +Totes les variables d'aquest grup, amb el seu tipus, el seu valor predeterminat i la seva descripció: + +{% include env_vars_table.html group="retention" %} diff --git a/i18n/ca/_configure/customization/security.md b/i18n/ca/_configure/customization/security.md new file mode 100644 index 0000000..cb0a7ad --- /dev/null +++ b/i18n/ca/_configure/customization/security.md @@ -0,0 +1,61 @@ +--- +layout: default +title: Variables de seguretat +parent: Variables d'entorn +nav_order: 6 +translated_from: af00832e0e69ea667004fbe5ebe635dd70ff3684 +--- + +# Variables de seguretat +{: .no_toc } + +Tokens, xifratge, hosts REST de sortida, emmascarament i els antics ajustos VAULT_* +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +Canvia aquestes variables per definir els teus propis secrets de token i de xifratge, i per limitar què poden cridar i mostrar els formularis. + +--- + +## Exemple + +Els teus propis secrets, crides REST limitades a una API i a una xarxa interna, i una clau emmascarada més. Al `.env` del projecte compose: + +```bash +ACCESS_TOKEN_SECRET=change-me-to-a-long-random-string +ENCRYPTION_SECRET=change-me-to-32-random-characters +REST_ALLOWED_HOSTS=api.example.com,10.20.0.0/16 +MASK_EXTRAVARS_REGEX=password|secret|token|apikey +``` + +Defineix `ENCRYPTION_SECRET` abans de desar la primera credencial. Des de la 7.3.0, definir-la o canviar-la torna a xifrar tots els secrets +desats a la següent arrencada, amb `ENCRYPTION_SECRET_PREVIOUS` indicant la clau antiga quan era teva, vegeu +[Canviar el secret de xifratge](../security/secrets.html#changing-the-encryption-secret). + +--- + +## Crides REST i jq + +Des de la 7.3.0 les funcions auxiliars REST (`fn.fnRestBasic`, `fn.fnRestAdvanced`, `fn.fnRestJwt`, `fn.fnRestJwtSecure`) comproven el +certificat de l'endpoint que criden, com qualsevol altra connexió; fins a la 7.2.0 no ho feien mai. S'hi apliquen tres ajustos: + +| Variable | Predeterminat | Efecte | +|---|---|---| +| [`REST_IGNORE_CERTS`](#env_REST_IGNORE_CERTS) | `0` | `1` omet la comprovació del certificat: només per a endpoints amb un certificat autosignat | +| [`REST_TIMEOUT_SECONDS`](#env_REST_TIMEOUT_SECONDS) | `60` | Quant espera una crida REST una resposta abans de fallar per temps d'espera esgotat | +| [`JQ_TIMEOUT_SECONDS`](#env_JQ_TIMEOUT_SECONDS) | `30` | Quant pot funcionar un filtre jq abans que s'aturi; la sortida de jq també està limitada a 64 MB | + +Totes tres tenen efecte en desar-les, sense reiniciar. Per a un endpoint el certificat del qual està signat per una CA privada, mantén la comprovació activada +i dona aquesta CA a Node.js: defineix `NODE_EXTRA_CA_CERTS` amb un fitxer PEM que la contingui a l'entorn de l'aplicació i reinicia l'aplicació. + +--- + +## Variables + +Totes les variables d'aquest grup, amb el seu tipus, el seu valor predeterminat i la seva descripció: + +{% include env_vars_table.html group="security" %} diff --git a/i18n/ca/_configure/customization/server.md b/i18n/ca/_configure/customization/server.md new file mode 100644 index 0000000..6470178 --- /dev/null +++ b/i18n/ca/_configure/customization/server.md @@ -0,0 +1,49 @@ +--- +layout: default +title: Servidor i base de dades +parent: Variables d'entorn +nav_order: 1 +translated_from: 0e4bba71dd8dd8efdf5ed7ff9c9644b1c0a89185 +--- + +# Servidor i base de dades +{: .no_toc } + +El servidor web, la connexió a MySQL, el compte d'admin i el que executa cada procés (AF_ROLE i les variables RTE_*) +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +Canvia aquestes variables quan l'aplicació s'executa darrere d'un proxy invers, en un altre port o contra una base de dades de fora del projecte compose. + +--- + +## Exemple + +Darrere d'un proxy invers que termina el TLS, sota `/ansibleforms`, amb un MySQL extern. A `docker-compose.yml`: + +```yaml + environment: + - BASE_URL=/ansibleforms # the proxy forwards /ansibleforms/ unchanged + - HTTPS=0 # the proxy terminates TLS + - PORT=8000 + - DB_HOST=mysql.example.com + - DB_PORT=3306 + - DB_USER=ansibleforms + - DB_PASSWORD=change-me +``` + +Aquestes línies substitueixen les línies `DB_*` i `PORT` que el fitxer compose ja hi té, que guanyen als mateixos noms de `.env`. Treu +el servei `mysqldb` i el `depends_on` que l'espera, i mapeja el port 8000 a `ports`. La part del proxy es descriu a la +pàgina [Proxy invers](../production/reverse-proxy.html). + +--- + +## Variables + +Totes les variables d'aquest grup, amb el seu tipus, el seu valor predeterminat i la seva descripció: + +{% include env_vars_table.html group="server" %} diff --git a/i18n/ca/_configure/disclaimer.md b/i18n/ca/_configure/disclaimer.md new file mode 100644 index 0000000..77ba0ac --- /dev/null +++ b/i18n/ca/_configure/disclaimer.md @@ -0,0 +1,56 @@ +--- +layout: default +title: Avís legal +nav_order: 7 +has_children: true +has_toc: false +permalink: /disclaimer.html +translated_from: a22b56db001904583c51e6bd28f1281737f32a32 +--- + +# Avís legal +{: .no_toc } + +Condicions que cada usuari accepta una vegada abans d'utilitzar l'aplicació, registrades amb qui ha acceptat quina versió i quan +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +Per a administradors: demana a tots els usuaris que acceptin unes condicions d'ús, a **Configuració > Accés > Avís legal**, amb l'opció de rol `showSettings`. + +Des de la 7.3.0 la pàgina llista totes les versions de l'avís legal, i cada versió s'obre en una pàgina pròpia amb les seves acceptacions. +Fins a la 7.2, la pàgina tenia en canvi tres pestanyes (**General**, **Versions** i **Acceptacions**); l'actualització conserva totes les versions. + +--- + +## En aquesta secció + +| Pàgina | Què hi trobaràs | +|---|---| +| [General](disclaimer/general.html) | La llista de versions, com afegir-ne una i com activar la que accepten els usuaris | +| [Versions](disclaimer/versions.html) | La pàgina d'una versió, i com canviar-ne el text com a correcció o tornar-lo a demanar a tothom | +| [Acceptacions](disclaimer/acceptances.html) | Qui ha acceptat quina versió, i com tornar-ho a demanar als usuaris que triïs | + + +--- + +## Què veuen els usuaris + +Amb una versió activada, tots els usuaris que inicien sessió la reben en un diàleg abans de res més, admins inclosos: + +1. En llegeixen el títol i el text. +2. Marquen la casella i després fan clic a **Accepta**. **Rebutja**, en vermell, els tanca la sessió. + +Des de la 7.3.0 la pàgina de darrere del diàleg es veu desenfocada fins que responen. + +Un usuari accepta cada versió una sola vegada: no se li torna a demanar al següent inici de sessió, només quan arriba una versió nova, quan +un admin desa un text canviat amb [Demana-ho a tothom de nou](disclaimer/versions.html#changing-the-text), o quan un admin fa servir +[Torna a demanar](disclaimer/acceptances.html#asking-users-again) sobre la seva acceptació. + +Fins que no l'accepten, l'API respon a cada crida de la seva sessió amb l'estat `403` i el codi `disclaimer_required`, +excepte les crides sota `/api/v2/disclaimer` i `/api/v2/profile`, i els esdeveniments en directe que segueix el navegador. +A un [token d'API](profile/api-token.html) no se li demana mai, ja que un script no té ningú que hi faci clic. + diff --git a/i18n/ca/_configure/disclaimer/acceptances.md b/i18n/ca/_configure/disclaimer/acceptances.md new file mode 100644 index 0000000..bc92bf4 --- /dev/null +++ b/i18n/ca/_configure/disclaimer/acceptances.md @@ -0,0 +1,41 @@ +--- +layout: default +title: Acceptacions +parent: Avís legal +nav_order: 3 +translated_from: 952000db809a111ac98ba2850a5eb8b31e7a96f5 +--- + +# Acceptacions +{: .no_toc } + +Qui ha acceptat quina versió, i com tornar-ho a demanar als usuaris que triïs +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +## Qui l'ha acceptat + +Cada acceptació es registra amb l'usuari i la versió, i la pestanya **Acceptacions** de la pàgina d'una versió les llista, la més recent primer: + +| Columna | Significat | +|---|---| +| **Usuari** | El nom d'usuari | +| **Inici de sessió** | Com ha iniciat sessió: Local, LDAP, Microsoft Entra ID o OpenID Connect | +| **Acceptat** | Quan | +| **Adreça IP** | Des d'on | +| **Navegador** | El seu navegador | + +--- + +## Tornar-ho a demanar + +Des de la 7.3.0 es pot demanar als usuaris que triïs que tornin a acceptar una versió, sense demanar-ho a tothom. + +**Torna a demanar**, al menú d'una fila o sobre les files marcades a la llista, esborra aquestes acceptacions després d'una confirmació: aquests usuaris +tornen a rebre l'avís legal a la seva propera petició, sense haver de tornar a iniciar sessió. La llista també es pot exportar, com qualsevol taula. + +El [registre d'auditoria](../production/logs.html#audit-trail) també registra cada acceptació, cada rebuig i cada canvi de l'avís legal. diff --git a/i18n/ca/_configure/disclaimer/general.md b/i18n/ca/_configure/disclaimer/general.md new file mode 100644 index 0000000..f76d1cc --- /dev/null +++ b/i18n/ca/_configure/disclaimer/general.md @@ -0,0 +1,58 @@ +--- +layout: default +title: General +parent: Avís legal +nav_order: 1 +translated_from: 5545e95acf978130082fcb459c917894e7a5286a +--- + +# General +{: .no_toc } + +La llista de versions, com afegir-ne una i com activar la que accepten els usuaris +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +## La llista + +Des de la 7.3.0, **Configuració > Accés > Avís legal** és una llista de les versions de l'avís legal, una per cada text tal com es va acceptar: + +| Columna | Significat | +|---|---| +| **Activat** | Si aquesta és la versió que accepten els usuaris; com a màxim n'hi ha una d'activada | +| **Versió** | El seu número, comptant des d'1 | +| **Títol** | El títol del seu diàleg | +| **Publicat per** | Qui l'ha afegida | +| **Publicat** | Quan | +| **Acceptacions** | Quants usuaris l'han acceptada | + +Un clic en una fila, o **Edita** al menú de la fila, obre la [pàgina de la versió](versions.html). El menú també té **Activa** o **Desactiva**, i **Suprimeix**. + +--- + +## Afegir una versió + +**Afegeix avís** obre un diàleg per a una versió nova, amb el número següent, que no queda activada fins que l'activis: + +| Camp | Significat | +|---|---| +| **Títol** | El títol del diàleg, com ara Condicions d'ús | +| **Text** | El que accepten els usuaris, com a màxim 20000 caràcters. Text pla: es conserven els salts de línia. | +| **Casella** | El que marquen els usuaris abans de poder acceptar, al principi "He llegit i accepto aquestes condicions." | + +Tots tres són obligatoris. La versió activada fins aleshores continua sent la que accepten els usuaris, així que pots preparar un text nou per endavant. + +--- + +## Activar una versió + +**Activa** al menú d'una fila, o l'interruptor **Activat** a la pàgina de la versió, converteix aquesta versió en la que accepten els usuaris i desactiva +les altres. + +Als usuaris que ja havien acceptat aquesta versió no se'ls torna a demanar, així que pots tornar a activar una versió anterior sense demanar-ho a tothom. +**Desactiva** a la versió activada desactiva l'avís legal fins que es torni a activar una versió; les versions i les acceptacions es conserven. +Suprimir una versió també en suprimeix les acceptacions, i suprimir l'activada desactiva l'avís legal. diff --git a/i18n/ca/_configure/disclaimer/versions.md b/i18n/ca/_configure/disclaimer/versions.md new file mode 100644 index 0000000..2fb47e1 --- /dev/null +++ b/i18n/ca/_configure/disclaimer/versions.md @@ -0,0 +1,43 @@ +--- +layout: default +title: Versions +parent: Avís legal +nav_order: 2 +translated_from: dcab4535a8f7e4aeaff321136564ab14d61dc3fa +--- + +# Versions +{: .no_toc } + +La pàgina d'una versió, i com canviar-ne el text com a correcció o tornar-lo a demanar a tothom +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +## La pàgina d'una versió + +Des de la 7.3.0 cada versió té una pàgina pròpia, a `/settings/disclaimer/`, amb dues pestanyes: + +| Pestanya | Què conté | +|---|---| +| **Detalls** | El títol, el text i el text de la casella, i l'interruptor **Activat**, que es desa a l'instant | +| **Acceptacions** | Qui ha acceptat aquesta versió, vegeu [Acceptacions](acceptances.html) | + +**Previsualització** mostra el diàleg tal com el veuran els usuaris, i **Suprimeix** elimina la versió juntament amb les seves acceptacions. El quadre de cerca +de sobre les pestanyes cerca a totes dues alhora: els camps que coincideixen a **Detalls** i les files que coincideixen a **Acceptacions**. + +--- + +## Canviar el text + +**Desa** sobre un títol, un text o un text de la casella modificats que els usuaris ja havien acceptat pregunta **Tornar-ho a demanar a tothom?**: + +| Resposta | Què passa | +|---|---| +| **Demana-ho a tothom de nou** | S'esborren les acceptacions d'aquesta versió, i cada usuari la torna a acceptar a la seva propera petició | +| **Mantén com a correcció** | El text es reescriu, per exemple per corregir una errada, i les acceptacions continuen comptant: no es torna a demanar a ningú | + +Una versió que encara no ha acceptat ningú es desa sense preguntar. Per conservar el text acceptat, [afegeix una versió nova](general.html#adding-a-version) i activa-la. diff --git a/i18n/ca/_configure/notification-channels.md b/i18n/ca/_configure/notification-channels.md new file mode 100644 index 0000000..798aafd --- /dev/null +++ b/i18n/ca/_configure/notification-channels.md @@ -0,0 +1,83 @@ +--- +layout: default +title: Canals de notificació +nav_order: 9 +has_children: true +has_toc: false +permalink: /notification-channels.html +translated_from: 1488a67f6f281b0236e4bad3a8b3d0c3bb32326c +--- + +# Canals de notificació +{: .no_toc } + +Envia sol·licituds d'aprovació i notificacions de tasques per correu, a Slack, Microsoft Teams, Telegram o a qualsevol webhook +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +Per a administradors: afegeix els servidors de correu i els canals de xat als quals els formularis envien les seves notificacions i aprovacions. + +--- + +## En aquesta secció + +| Pàgina | Què hi trobaràs | +|---|---| +| [Correu](notification-channels/mail.html) | Els servidors SMTP, el predeterminat i el seu inici de sessió | +| [Slack i Microsoft Teams](notification-channels/slack-and-teams.html) | El webhook d'un canal de Slack o de Teams | +| [Telegram](notification-channels/telegram.html) | Un bot que publica en un xat de Telegram | +| [Webhook](notification-channels/webhook.html) | Una petició JSON a qualsevol endpoint HTTP | +| [Utilitzar canals en un formulari](notification-channels/in-a-form.html) | Com nomenar canals a les notificacions i a les aprovacions | +| [Provar un canal](notification-channels/testing.html) | Envia una prova, i què demostra | + + +--- + +## Com funciona + +Un **canal de notificació** és un lloc on van les notificacions, que s'afegeix a **Connexions > Notificacions**. Cada canal és +d'un d'aquests tipus: + +| Tipus | Què envia | +|---|---| +| Correu | Correu a través d'un servidor SMTP: sol·licituds d'aprovació i notificacions de tasques. | +| Slack | Un missatge en un canal de Slack, mitjançant el seu webhook d'entrada, amb un botó que porta a la tasca. | +| Microsoft Teams | Una targeta en un canal de Teams, mitjançant un webhook de Workflows, amb un botó que porta a la tasca. | +| Telegram | Un missatge d'un bot en un xat de Telegram, amb un enllaç a la tasca. | +| Webhook | Una petició JSON a qualsevol endpoint HTTP, construïda a partir d'una plantilla. | + +Un formulari nomena els seus canals a les seves [notificacions](forms/notifications.html) i a la seva [aprovació](forms/approval.html), +amb `channels:`. Una notificació que no es pot enviar s'escriu al registre; mai no fa fallar la tasca ni l'aprovació. + +--- + +## La pàgina de notificacions + +La pàgina de **Connexions > Notificacions** llista tots els canals amb aquestes columnes: + +| Columna | Significat | +|---|---| +| Activat | Si se li envien notificacions, vegeu [Utilitzar canals en un formulari](notification-channels/in-a-form.html). | +| Nom | Com el nomenen els formularis a `channels:`. | +| Tipus | Correu, Slack, Microsoft Teams, Telegram o Webhook. El canal de correu predeterminat mostra una etiqueta **Predeterminat** després del seu tipus. | +| Descripció | Per a què serveix el canal. | + +**Afegeix canal de notificació** obre un diàleg: **Canal** (nom i descripció), **Tipus** i després els passos del tipus +triat. El tipus es fixa quan es crea el canal i ja no canvia. Una fila obre la pàgina pròpia del canal, amb els mateixos passos com a +pestanyes després de **Detalls**, i **Envia una prova**, **Suprimeix** i **Desa** a dalt a la dreta. El menú de la fila ofereix +**Edita**, **Activa** o **Desactiva** (segons correspongui), **Fes-lo predeterminat** (correu), **Envia una prova** i **Suprimeix**. + +La pestanya **Detalls** de la pàgina d'un canal conté l'interruptor **Activat**, que es desa a l'instant, i per al correu l'interruptor +**Predeterminat**, que es desa amb **Desa**. + +Un usuari que obre aquestes pàgines amb `showConnectionsSettings` però sense el rol d'admin no pot triar una credencial que només +pot nomenar un admin, vegeu [Qui pot canviar una credencial](credentials.html#who-may-change-a-credential). Quan un usuari així canvia +on envia un canal (la url d'un webhook o la seva comprovació del certificat, l'adreça de la Bot API de Telegram), el canal perd la +credencial que nomenava, tret que en triï una en el mateix canvi. + +Un canal declarat a la [llavor de configuració](seed/) és només de lectura en aquesta pàgina, i tot i així es pot provar. + diff --git a/i18n/ca/_configure/notification-channels/in-a-form.md b/i18n/ca/_configure/notification-channels/in-a-form.md new file mode 100644 index 0000000..b6816e4 --- /dev/null +++ b/i18n/ca/_configure/notification-channels/in-a-form.md @@ -0,0 +1,41 @@ +--- +layout: default +title: Utilitzar canals en un formulari +parent: Canals de notificació +nav_order: 5 +translated_from: ab807b79469429faf3c3838f268af1ba6c29805a +--- + +# Utilitzar canals en un formulari +{: .no_toc } + +Com nomenar canals a les notificacions i a les aprovacions +{: .fs-6 .fw-300 } + +Els formularis nomenen els canals pel seu nom, a `notifications` per a l'estat i els esdeveniments de la tasca, i a `approval`: + +```yaml +notifications: + recipients: + - ops@example.com + channels: + - ops-slack + - ops-teams + onStatus: + - failed + +approval: + title: Remove host $(vm.name) ? + roles: + - approvers + channels: + - approvers-teams +``` + +- Els canals de xat i de webhook reben un missatge breu (el formulari, la tasca, què ha passat) amb un enllaç a la tasca; en una + aprovació, la pàgina de la tasca és on s'aprova o es rebutja. +- Un canal de **correu** de la llista envia el correu habitual a `recipients` (les adreces de `notifications` d'una aprovació) a través + d'aquest servidor en lloc del predeterminat. +- Un nom que no existeix, o un canal de xat o de webhook desactivat, s'omet i s'indica al registre. +- Un canal de **correu** desactivat no s'omet: el correu surt pel canal de correu predeterminat, i el + registre ho indica. diff --git a/i18n/ca/_configure/notification-channels/mail.md b/i18n/ca/_configure/notification-channels/mail.md new file mode 100644 index 0000000..b23e2e8 --- /dev/null +++ b/i18n/ca/_configure/notification-channels/mail.md @@ -0,0 +1,24 @@ +--- +layout: default +title: Correu +parent: Canals de notificació +nav_order: 1 +translated_from: 3ab21a1f2987744527863f5f25ce347dbdf2cd3d +--- + +# Correu +{: .no_toc } + +Els servidors SMTP, el predeterminat i el seu inici de sessió +{: .fs-6 .fw-300 } + +Un canal de correu és un servidor SMTP. En pots tenir diversos; el marcat com a **Predeterminat** és el servidor amb què l'aplicació envia el seu +correu quan un formulari no nomena cap canal de correu. El primer canal de correu passa a ser el predeterminat, i **Fes-lo predeterminat** el canvia. + +| Pas | Camp | Significat | +|---|---|---| +| Credencials | Credencial | Obligatori. Una credencial **smtp** de [Connexions > Credencials](../credentials.html): el servidor de correu, el seu port i TLS, i l'inici de sessió. Per a un relay sense inici de sessió, una credencial smtp sense usuari. | +| Remitent | Remitent | L'adreça del remitent que veuen els destinataris. | + +L'interruptor **Predeterminat** de la pestanya **Detalls** de la pàgina d'un canal de correu el converteix en el predeterminat, igual que **Fes-lo predeterminat**. +Els ajustos de correu de la llavor de configuració s'utilitzen mentre cap canal de correu no sigui el predeterminat, o mentre el predeterminat estigui desactivat. diff --git a/i18n/ca/_configure/notification-channels/slack-and-teams.md b/i18n/ca/_configure/notification-channels/slack-and-teams.md new file mode 100644 index 0000000..ed03d76 --- /dev/null +++ b/i18n/ca/_configure/notification-channels/slack-and-teams.md @@ -0,0 +1,22 @@ +--- +layout: default +title: Slack i Microsoft Teams +parent: Canals de notificació +nav_order: 2 +translated_from: d0c548d54213641c8b6b142e1d7cd1764b6d02b9 +--- + +# Slack i Microsoft Teams +{: .no_toc } + +El webhook d'un canal de Slack o de Teams +{: .fs-6 .fw-300 } + +Els canals de Slack i de Teams només necessiten l'adreça del webhook del canal: + +| Tipus | Adreça del webhook | +|---|---| +| Slack | El webhook d'entrada del canal (Slack app > Incoming Webhooks). | +| Microsoft Teams | El webhook de Workflows del canal ("post to a channel when a webhook request is received"). | + +L'adreça és el secret que permet a qualsevol publicar al canal: es desa xifrada i no es torna a mostrar mai un cop desada. diff --git a/i18n/ca/_configure/notification-channels/telegram.md b/i18n/ca/_configure/notification-channels/telegram.md new file mode 100644 index 0000000..247fff5 --- /dev/null +++ b/i18n/ca/_configure/notification-channels/telegram.md @@ -0,0 +1,21 @@ +--- +layout: default +title: Telegram +parent: Canals de notificació +nav_order: 3 +translated_from: c268bd1ed02b399d229ecec8e49d7ba4956ee131 +--- + +# Telegram +{: .no_toc } + +Un bot que publica en un xat de Telegram +{: .fs-6 .fw-300 } + +Un canal de Telegram és un bot que publica en un xat. El seu pas **Credencials** conté el **Token del bot**, i el seu pas **Bot**, la resta: + +| Camp | Significat | +|---|---| +| Token del bot | Una credencial **api** de [Connexions > Credencials](../credentials.html) la contrasenya de la qual és el token del bot que dona BotFather. | +| Id del xat | El xat, el grup o el canal on publica el bot; un nombre negatiu per a un grup o un canal. | +| Adreça de la Bot API | Un servidor Bot API propi; buit per a `api.telegram.org`. | diff --git a/i18n/ca/_configure/notification-channels/testing.md b/i18n/ca/_configure/notification-channels/testing.md new file mode 100644 index 0000000..1ed9011 --- /dev/null +++ b/i18n/ca/_configure/notification-channels/testing.md @@ -0,0 +1,18 @@ +--- +layout: default +title: Provar un canal +parent: Canals de notificació +nav_order: 6 +translated_from: ae699fb758338a45780631ffec3f85ef3401280f +--- + +# Provar un canal +{: .no_toc } + +Envia una prova, i què demostra +{: .fs-6 .fw-300 } + +**Envia una prova** envia una notificació de prova a través del canal tal com està desat, així que desa abans els teus canvis. També funciona amb un canal +desactivat. Per a un canal de correu +el diàleg demana l'adreça on enviar-la; els altres publiquen al seu propi canal. El diàleg mostra si ha funcionat +i, si no, el motiu. diff --git a/i18n/ca/_configure/notification-channels/webhook.md b/i18n/ca/_configure/notification-channels/webhook.md new file mode 100644 index 0000000..4b86856 --- /dev/null +++ b/i18n/ca/_configure/notification-channels/webhook.md @@ -0,0 +1,53 @@ +--- +layout: default +title: Webhook +parent: Canals de notificació +nav_order: 4 +translated_from: 99bafedd6f37d6afe3104cd7d8819c3891b518d0 +--- + +# Webhook +{: .no_toc } + +Una petició JSON a qualsevol endpoint HTTP +{: .fs-6 .fw-300 } + +Un canal webhook envia una petició JSON a qualsevol endpoint HTTP. El seu pas **Endpoint** indica on i com, i el seu pas +**Credencials** conté el **Token bearer**: + +| Camp | Significat | +|---|---| +| Url | L'adreça a la qual s'envia la petició. | +| Mètode | `POST` (predeterminat) o `PUT`. | +| Token bearer | Una credencial **api** de [Connexions > Credencials](../credentials.html) la contrasenya de la qual s'envia com a `Authorization: Bearer `. Buit: sense token. | +| Comprova el certificat TLS | Activat per defecte; desactiva'l només per a un endpoint amb un certificat autosignat. | + +{% raw %} +El seu pas **Contingut** conté les **Capçaleres**, capçaleres addicionals com un objecte JSON, per exemple `{ "X-Source": "ansibleforms" }`, i el +**Contingut**, la plantilla JSON del cos. S'emplenen aquests marcadors: + +| Marcador | Valor | +|---|---| +| `{{title}}` | El títol de la notificació | +| `{{text}}` | El seu text | +| `{{status}}` | L'estat de la tasca | +| `{{event}}` | L'esdeveniment de la tasca | +| `{{jobId}}` | L'id de la tasca | +| `{{form}}` | El nom del formulari | +| `{{user}}` | L'usuari que ha iniciat la tasca | +| `{{link}}` | L'enllaç a la tasca | + +Un marcador que ocupa tota una cadena JSON (`"{{text}}"`) se substitueix pel valor com a JSON; dins d'una cadena més llarga, el seu +text s'escapa per a JSON. Un marcador desconegut es deixa tal com està escrit. Un contingut buit envia aquesta plantilla: + +```json +{ + "title": "{{title}}", + "text": "{{text}}", + "status": "{{status}}", + "event": "{{event}}", + "job": { "id": "{{jobId}}", "form": "{{form}}", "user": "{{user}}" }, + "link": "{{link}}" +} +``` +{% endraw %} diff --git a/i18n/ca/_configure/production/backups.md b/i18n/ca/_configure/production/backups.md new file mode 100644 index 0000000..e0bfdd1 --- /dev/null +++ b/i18n/ca/_configure/production/backups.md @@ -0,0 +1,111 @@ +--- +layout: default +title: Còpies de seguretat +parent: En producció +nav_order: 2 +redirect_from: + - /production/backups-and-logs.html +translated_from: 85cd29062adaaa52a93b688dcaddda94ef40a7bd +--- + +# Còpies de seguretat +{: .no_toc } + +Còpies nocturnes, què contenen, restauracions, i què més cal conservar +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +## Còpies nocturnes + +AnsibleForms fa una còpia de seguretat de si mateix cada nit a mitjanit, a la zona horària de [`LOG_TZ`](../customization/logging.html#env_LOG_TZ) +(UTC per defecte). Aquests ajustos la controlen: + +| Variable | Predeterminat | Significat | +|----------|---------|---------| +| [`BACKUP_PATH`](../customization/paths.html#env_BACKUP_PATH) | `%PERSISTENT_FOLDER%/backups` | On s'escriuen les còpies de seguretat, cadascuna en una carpeta amb marca de temps | +| [`NIGHTLY_BACKUP_RETENTION`](../customization/retention.html#env_NIGHTLY_BACKUP_RETENTION) | `7` | Quantes còpies nocturnes es conserven; `0` les conserva totes | +| [`MYSQLDUMP_COMMAND`](../customization/retention.html#env_MYSQLDUMP_COMMAND) | `mariadb-dump --ssl-verify-server-cert=OFF` | L'ordre que bolca la base de dades | +| [`MYSQL_COMMAND`](../customization/retention.html#env_MYSQL_COMMAND) | `mariadb --ssl-verify-server-cert=OFF` | L'ordre que reprodueix un bolcat en restaurar | +| [`BACKUP_COMMAND_TIMEOUT_SECONDS`](../customization/retention.html#env_BACKUP_COMMAND_TIMEOUT_SECONDS) | `3600` | Quant de temps poden durar el bolcat i la restauració | + +Els usuaris amb l'opció de rol `allowBackupOps` també poden fer una còpia de seguretat en qualsevol moment a la pàgina **Còpies de seguretat**. La retenció +només elimina les còpies nocturnes, i només hi compten les còpies amb un bolcat utilitzable, de manera que una sèrie de nits fallides +mai no fa fora l'última còpia bona. + +Abans que una actualització canviï la base de dades, el worker fa primer una còpia de seguretat normal, una per versió, anomenada *Before the upgrade to +<version>*. Es mostra a la pàgina **Còpies de seguretat** i la retenció nocturna no l'elimina mai. Si falla (no hi ha eina de bolcat, +no es pot escriure a `BACKUP_PATH`), l'actualització s'atura i n'explica el motiu, de manera que l'aplicació mai no arrenca sobre una base de dades a mig actualitzar. +[`UPGRADE_BACKUP`](../customization/retention.html#env_UPGRADE_BACKUP)`=0` actualitza sense còpia de seguretat. + +Les ordres poden ser embolcalls com ara `docker exec mysqldump`, si la seva primera paraula existeix localment. Des de la 7.3.0 s'executen +sense shell: les cometes i `$NAME` de l'entorn de l'ordre funcionen, però `;`, `|`, `&&`, `>` i `<` es rebutgen. + +--- + +## Permisos de la base de dades + +El bolcat s'executa com a [`DB_USER`](../customization/server.html#env_DB_USER), i no necessita més permisos que els que necessita la mateixa aplicació: + +```sql +CREATE USER 'ansibleforms'@'%' IDENTIFIED BY ''; +GRANT ALL PRIVILEGES ON `AnsibleForms`.* TO 'ansibleforms'@'%'; +``` + +El bolcat es fa amb `--no-tablespaces`, de manera que no cal el permís `PROCESS` de tot el servidor, i omet les taules +que descriuen els processos en execució (`nodes`, `cache_epochs`, `designer_lock`, `runner_leases`). La restauració el reprodueix amb el mateix usuari. +La pàgina **Estat** mostra un avís a la comprovació **Usuari de la base de dades** quan l'usuari té permisos sobre totes les bases de dades, com en té `root`. + +--- + +## Què conté una còpia de seguretat + +Cada còpia de seguretat és una carpeta sota `BACKUP_PATH`, amb el nom de la seva marca de temps UTC (`YYYYMMDDHHmmss`), que conté: + +| Fitxer | Contingut | +|------|---------| +| `ansibleforms.sql` | El bolcat de la base de dades `AnsibleForms`: usuaris, grups, credencials, tasques, ajustos, el rastre d'auditoria | +| `config.yaml` | El fitxer de [`CONFIG_PATH`](../customization/paths.html#env_CONFIG_PATH) | +| `forms/` | La carpeta de [`FORMS_FOLDER_PATH`](../customization/paths.html#env_FORMS_FOLDER_PATH) | +| `managed.env` | El fitxer d'entorn que escriuen les pàgines de configuració, sense `ENCRYPTION_SECRET`, `ENCRYPTION_SECRET_PREVIOUS` ni `ACCESS_TOKEN_SECRET` | +| `meta.yaml` | La descripció de la còpia de seguretat | + +Una còpia de seguretat el bolcat de la qual falla s'elimina de nou i es registra com a error. La pàgina **Estat** avisa quan no hi ha cap còpia, +quan la més recent té més de dos dies o quan no té cap bolcat utilitzable, i comprova que l'eina de bolcat existeix. + +En canvi, [`OLD_BACKUP_DAYS`](../customization/retention.html#env_OLD_BACKUP_DAYS) conserva els punts de restauració del dissenyador (60 dies per defecte). + +--- + +## Restaurar una còpia de seguretat + +Restaura des de la [pàgina **Còpies de seguretat**](../gui/administration.html#restore), amb **Crea una còpia de seguretat nova abans de restaurar** marcat. Una restauració: + +* reprodueix `ansibleforms.sql`, que substitueix tota la base de dades; des de la 7.3.0 una còpia d'una versió anterior es torna a actualitzar + després, com a l'inici d'una versió nova, i s'informa d'un pedaç que falla +* torna a copiar `config.yaml`, i substitueix la carpeta `forms/` per la de la còpia: des de la 7.3.0 els formularis que no són a la còpia + s'eliminen en lloc de conservar-se, els enllaços i el mode de la carpeta es mantenen, i una còpia fallida fa tornar la carpeta enrere +* **no** restaura `managed.env`, perquè descriu l'amfitrió d'on prové la còpia. El botó **Restaura l'entorn** + el torna a posar si es demana, conserva el fitxer actual com a `.env.bak`, i necessita un reinici. + +Una còpia de seguretat sense un bolcat utilitzable es rebutja; després d'una restauració interrompuda, corregeix la causa i torna a restaurar. + +En un amfitrió nou, defineix el mateix `ENCRYPTION_SECRET` abans de restaurar, o les credencials desades no es podran desxifrar. + +--- + +## Què més cal copiar + +La còpia nocturna cobreix la base de dades, la configuració i els formularis, però res més de la carpeta persistent: + +* **`ENCRYPTION_SECRET` i `ACCESS_TOKEN_SECRET`** : mai no són en una còpia de seguretat, a propòsit. Guarda'ls al teu gestor de secrets; + sense el secret de xifratge, un bolcat de la base de dades no serveix de res per a les credencials. +* **les mateixes còpies de seguretat** : són al mateix volum que la instància. Copia `BACKUP_PATH` a un altre amfitrió. +* **la resta de la carpeta persistent** : playbooks, fitxers pujats, fitxers de variables, repositoris clonats, certificats i registres. + Amb el projecte docker-compose, fes una còpia de tota la carpeta `data/`, que també conté la clau SSH, les funcions + personalitzades i els rols i les col·leccions d'Ansible. + +El contingut que ve de git (repositoris, formularis en un repositori) es pot tornar a clonar, així que la seva còpia importa menys. diff --git a/i18n/ca/_configure/production/index.md b/i18n/ca/_configure/production/index.md new file mode 100644 index 0000000..c867188 --- /dev/null +++ b/i18n/ca/_configure/production/index.md @@ -0,0 +1,60 @@ +--- +layout: default +title: En producció +nav_order: 12 +has_children: true +has_toc: false +permalink: /production/ +translated_from: 2d7f4be84a76837fae34c1b414a229448bfae4ea +--- + +# En producció +{: .no_toc } + +Publica, fes còpies de seguretat i supervisa una instància de la qual depenen persones +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +## Abans de posar-la en marxa + +Els valors predeterminats posen una instància en marxa ràpidament, però alguns només estan pensats per a una primera ullada. AnsibleForms +registra un avís `[SECURITY]` en arrencar quan `ENCRYPTION_SECRET` o `ACCESS_TOKEN_SECRET` no estan definides, i la +pàgina **Estat** informa de les còpies de seguretat, dels ajustos de retenció i del sanejador d'expressions. + +--- + +## Llista de comprovació per a producció + +Revisa aquests punts una vegada abans que els usuaris depenguin de la instància, i un altre cop després d'una actualització important: + +| Punt | Què cal fer | Detalls | +|------|------------|---------| +| Contrasenya de l'admin | Canvia la contrasenya del compte d'admin local | [Enduriment](../security/hardening.html#the-admin-account) | +| Secret de xifratge | Defineix [`ENCRYPTION_SECRET`](../customization/security.html#env_ENCRYPTION_SECRET) abans de desar cap credencial | [Secrets i xifratge](../security/secrets.html#the-two-master-secrets) | +| Secret dels tokens | Defineix [`ACCESS_TOKEN_SECRET`](../customization/security.html#env_ACCESS_TOKEN_SECRET), perquè les sessions sobrevisquin a un reinici | [Secrets i xifratge](../security/secrets.html#the-two-master-secrets) | +| HTTPS | Termina el TLS amb el teu propi certificat, no amb el d'exemple | [HTTPS](../security/https.html) | +| Proxy invers | Publica la instància darrere d'un proxy, opcionalment sota [`BASE_URL`](../customization/server.html#env_BASE_URL) | [Proxy invers](reverse-proxy.html) | +| Endpoint de l'esquema | Posa [`ALLOW_SCHEMA_CREATION`](../customization/server.html#env_ALLOW_SCHEMA_CREATION) a `0` un cop existeix l'esquema | [Enduriment](../security/hardening.html#the-database) | +| Crides de sortida | Restringeix les expressions REST amb [`REST_DENIED_HOSTS`](../customization/security.html#env_REST_DENIED_HOSTS) | [Enduriment](../security/hardening.html#expressions-and-outbound-calls) | +| Funcions opcionals | Deixa MCP i l'assistent de xat desactivats si no els fas servir | [Enduriment](../security/hardening.html#optional-features) | +| Còpies de seguretat | Comprova que la còpia nocturna funciona, i copia-la fora de l'amfitrió | [Còpies de seguretat](backups.html) | +| Retenció | Decideix quant de temps es conserven les tasques i les entrades d'auditoria | [Registres](logs.html#retention) | + +--- + +## En aquesta secció + +Cada tema té la seva pròpia pàgina; la protecció de la instància es tracta a [Seguretat](../security/): + +| Pàgina | Què hi trobaràs | +|---|---| +| [Proxy invers](reverse-proxy.html) | Publicar AnsibleForms darrere de Nginx, Traefik o Apache, a l'arrel o sota un subcamí | +| [Còpies de seguretat](backups.html) | Còpies nocturnes, què contenen, restauracions, i què més cal conservar | +| [Registres](logs.html) | Fitxers de registre, syslog, el rastre d'auditoria, i la retenció de tasques i entrades d'auditoria | +| [Escalat](scaling.html) | Diversos nodes d'aplicació amb un worker; l'RTE té la seva pròpia secció, [Entorns d'execució](../rte/) | +| [Supervisió](monitoring.html) | Sondes de salut, mètriques de Prometheus i la pàgina Estat | + diff --git a/i18n/ca/_configure/production/logs.md b/i18n/ca/_configure/production/logs.md new file mode 100644 index 0000000..7b2e391 --- /dev/null +++ b/i18n/ca/_configure/production/logs.md @@ -0,0 +1,126 @@ +--- +layout: default +title: Registres +parent: En producció +nav_order: 3 +translated_from: 17d3894c528610d4916fbdcf4beb5bbbacd2b266 +--- + +# Registres +{: .no_toc } + +Fitxers de registre, syslog, el rastre d'auditoria, i quant de temps es conserven les tasques i les entrades d'auditoria +{: .fs-6 .fw-300 } + +1. TOC +{:toc} + +--- + +## Fitxers de registre + +AnsibleForms escriu dos registres amb rotació diària a [`LOG_PATH`](../customization/logging.html#env_LOG_PATH) +(`%PERSISTENT_FOLDER%/logs`), comprimeix els dies anteriors i els conserva durant [`LOG_RETENTION_DAYS`](../customization/logging.html#env_LOG_RETENTION_DAYS) +(30 per defecte, `0` conserva tots els fitxers; un canvi a la pàgina de configuració s'aplica a l'instant): + +* `ansibleforms..log` : tot el que és de nivell [`LOG_LEVEL`](../customization/logging.html#env_LOG_LEVEL) o superior +* `ansibleforms.errors..log` : només els errors + +La consola, que es llegeix amb `docker logs` o `kubectl logs`, té el seu propi nivell, +[`LOG_CONSOLE_LEVEL`](../customization/logging.html#env_LOG_CONSOLE_LEVEL). Tots dos són `notice` per defecte, que és l'adequat per a +producció; fes servir `info` o `debug` només mentre investigues un problema, i deixa +[`ENABLE_DB_QUERY_LOGGING`](../customization/features.html#env_ENABLE_DB_QUERY_LOGGING) desactivat. Els nivells es poden canviar a +les pàgines de configuració sense reiniciar, i la pàgina **Registre del servidor** mostra el registre als usuaris amb l'opció `showLogs`. + +--- + +## Línies JSON + +Per a un col·lector de registres com ara Loki, ELK o Splunk, posa [`LOG_FORMAT`](../customization/logging.html#env_LOG_FORMAT) a `json`. Cada +línia, a la consola i als fitxers, és llavors un objecte JSON en lloc de `