diff --git a/assets/branding/darkblue.jpg b/assets/branding/darkblue.jpg index eaceb19..7d02d1f 100644 Binary files a/assets/branding/darkblue.jpg and b/assets/branding/darkblue.jpg differ diff --git a/docs/release-0.6.5.md b/docs/release-0.6.5.md new file mode 100644 index 0000000..ea0a822 --- /dev/null +++ b/docs/release-0.6.5.md @@ -0,0 +1,26 @@ +# SGU Credential Provider 0.6.5 + +Esta versión actualiza los fondos de bienvenida de Windows y Linux sin agregar +dependencias ni trabajo de composición durante el inicio de sesión. + +## Identidad visual + +- El fondo base azul incorpora de forma permanente el logotipo blanco oficial + de Universidad La Salle México. +- El generador utiliza directamente ese JPEG: no abre, redimensiona ni compone + un segundo archivo de logotipo cada vez que inicia una sesión. +- Se conservan las dimensiones institucionales de `1600x1000` y el área central + disponible para el saludo personalizado. + +## Texto de ubicación + +- La sala aparece en una primera línea de mayor tamaño. +- La dependencia aparece debajo con una tipografía menor. +- La redacción neutral usa `Acceso a...`; cuando Active Directory contiene el + sexo enriquecido, usa `Estás ubicado...` o `Estás ubicada...`. +- La misma lógica está incluida en los enrolamientos de Windows y Linux. +- Si faltan el sexo o los metadatos de ubicación, permanecen los fallbacks + neutrales documentados y el inicio de sesión no se bloquea. + +Los perfiles de usuario locales y el rollback de roaming introducido en 0.6.4 +no cambian en esta versión. diff --git a/docs/welcome-wallpaper.md b/docs/welcome-wallpaper.md index 2fb471b..4804d61 100644 --- a/docs/welcome-wallpaper.md +++ b/docs/welcome-wallpaper.md @@ -1,7 +1,10 @@ # Fondo de bienvenida personalizado -El enrolamiento instala un fondo base azul, las familias `Indivisa Text Sans` y -`Indivisa Text Serif`, y un generador local. La GPO de equipos +El enrolamiento instala un fondo base azul que ya contiene el logotipo blanco +oficial de Universidad La Salle México, las familias `Indivisa Text Sans` y +`Indivisa Text Serif`, y un generador local. El logotipo está horneado en +`assets/branding/darkblue.jpg`: el generador no carga, redimensiona ni compone +otro logo durante el inicio de sesión. La GPO de equipos `SGU - Windows client experience` ejecuta el generador al abrir cada sesión y mantiene el fondo base en la pantalla de bloqueo. @@ -28,12 +31,18 @@ restaura el comando genérico de inicio. El saludo usa `Bienvenido/ubicado` para `Male` y `Bienvenida/ubicada` para `Female`. Cuando el enriquecimiento no produjo este dato, utiliza la redacción -neutral `Te damos la bienvenida` y `Ubicación:`. El texto secundario sigue estas -reglas: +neutral `Te damos la bienvenida` y `Acceso`. La ubicación se divide en dos +líneas: la sala ocupa la primera y la dependencia aparece debajo con un tamaño +menor. Sigue estas reglas: -1. Con `location` y OU: `Acceso al Aula Flexible del Centro de Experiencia Digital.` -2. Con sólo uno de los datos: muestra únicamente el dato disponible. -3. Sin ambos: el texto adaptado `Bienvenido/Bienvenida al Laboratorio...`; sin +1. Sin sexo: `Acceso a la Sala de Aplicaciones`, seguido por + `del Laboratorio de Cómputo de Ingeniería.` +2. Masculino: `Estás ubicado en el Aula Flexible`, seguido por + `del Centro de Experiencia Digital.` +3. Femenino: `Estás ubicada en la Sala de Redes`, seguido por + `del Laboratorio de Cómputo de Ingeniería.` +4. Con sólo uno de los datos: muestra únicamente el dato disponible. +5. Sin ambos: el texto adaptado `Bienvenido/Bienvenida al Laboratorio...`; sin sexo disponible, la forma neutral `Acceso al Laboratorio de Cómputo de Ingeniería.` La ausencia de AD, de un atributo o de una tipografía nunca bloquea la sesión. diff --git a/scripts/Set-SguWelcomeWallpaper.ps1 b/scripts/Set-SguWelcomeWallpaper.ps1 index 070c8a5..5555c6b 100644 --- a/scripts/Set-SguWelcomeWallpaper.ps1 +++ b/scripts/Set-SguWelcomeWallpaper.ps1 @@ -189,7 +189,7 @@ function Get-WelcomeLocationText { $located = switch ($Gender) { 'Male' { 'Est{0}s ubicado en' -f [char]0x00E1 } 'Female' { 'Est{0}s ubicada en' -f [char]0x00E1 } - default { 'Ubicaci{0}n:' -f [char]0x00F3 } + default { $null } } $engineeringLab = switch ($Gender) { 'Male' { 'Bienvenido al Laboratorio de C{0}mputo de Ingenier{1}a.' -f [char]0x00F3,[char]0x00ED } @@ -202,7 +202,10 @@ function Get-WelcomeLocationText { if ($Room -and $OuName) { $roomArticle = Get-SpanishArticle -Value $Room $ouArticle = Get-SpanishArticle -Value $OuName - $roomPhrase = if ($roomArticle -eq 'el') { + $roomPhrase = if ($Gender) { + if ($roomArticle) { "$roomArticle $Room" } else { $Room } + } + elseif ($roomArticle -eq 'el') { "al $Room" } elseif ($roomArticle) { @@ -212,17 +215,26 @@ function Get-WelcomeLocationText { "a $Room" } $ouPhrase = if ($ouArticle -eq 'el') { "del $OuName" } elseif ($ouArticle) { "de $ouArticle $OuName" } else { "de $OuName" } - return "Acceso $roomPhrase $ouPhrase." + $primary = if ($Gender) { "$located $roomPhrase" } else { "Acceso $roomPhrase" } + return "$primary`n$ouPhrase." } if ($Room) { $article = Get-SpanishArticle -Value $Room - $phrase = if ($article) { "$article $Room" } else { $Room } - return "$located $phrase." + if ($Gender) { + $phrase = if ($article) { "$article $Room" } else { $Room } + return "$located $phrase." + } + $destination = if ($article -eq 'el') { "al $Room" } elseif ($article) { "a $article $Room" } else { "a $Room" } + return "Acceso $destination." } if ($OuName) { $article = Get-SpanishArticle -Value $OuName - $phrase = if ($article) { "$article $OuName" } else { $OuName } - return "$located $phrase." + if ($Gender) { + $phrase = if ($article) { "$article $OuName" } else { $OuName } + return "$located $phrase." + } + $destination = if ($article -eq 'el') { "al $OuName" } elseif ($article) { "a $article $OuName" } else { "a $OuName" } + return "Acceso $destination." } return $engineeringLab } @@ -350,6 +362,9 @@ if (-not $PSBoundParameters.ContainsKey('OrganizationalUnit')) { } } $locationText = Get-WelcomeLocationText -Room $Location -OuName $OrganizationalUnit -Gender $Gender +$locationLines = @($locationText -split '\r?\n', 2) +$locationPrimaryText = $locationLines[0] +$locationSecondaryText = if ($locationLines.Count -gt 1) { $locationLines[1] } else { $null } if (-not $CanvasWidth -or -not $CanvasHeight) { try { @@ -436,6 +451,8 @@ try { -PreferredStyle ([Drawing.FontStyle]::Bold -bor [Drawing.FontStyle]::Italic) $locationFont = New-WelcomeFont -Family $sansFamily -Size ([single](27 * $scale)) ` -PreferredStyle ([Drawing.FontStyle]::Regular) + $locationSecondaryFont = New-WelcomeFont -Family $sansFamily -Size ([single](20 * $scale)) ` + -PreferredStyle ([Drawing.FontStyle]::Regular) $format = [Drawing.StringFormat]::new() $format.Alignment = [Drawing.StringAlignment]::Center $format.LineAlignment = [Drawing.StringAlignment]::Center @@ -447,11 +464,20 @@ try { Draw-CenteredText -Graphics $graphics -Text $DisplayName -Font $nameFont ` -Brush $whiteBrush -Bounds ([Drawing.RectangleF]::new($panelX + 30*$scale, $panelY + 64*$scale, $panelWidth - 60*$scale, 105*$scale)) -Format $format $graphics.DrawLine($linePen, $panelX + 150*$scale, $panelY + 180*$scale, $panelX + $panelWidth - 150*$scale, $panelY + 180*$scale) - Draw-CenteredText -Graphics $graphics -Text $locationText -Font $locationFont ` - -Brush $accentBrush -Bounds ([Drawing.RectangleF]::new($panelX + 60*$scale, $panelY + 190*$scale, $panelWidth - 120*$scale, 94*$scale)) -Format $format + if ($locationSecondaryText) { + Draw-CenteredText -Graphics $graphics -Text $locationPrimaryText -Font $locationFont ` + -Brush $accentBrush -Bounds ([Drawing.RectangleF]::new($panelX + 60*$scale, $panelY + 190*$scale, $panelWidth - 120*$scale, 46*$scale)) -Format $format + Draw-CenteredText -Graphics $graphics -Text $locationSecondaryText -Font $locationSecondaryFont ` + -Brush $accentBrush -Bounds ([Drawing.RectangleF]::new($panelX + 60*$scale, $panelY + 235*$scale, $panelWidth - 120*$scale, 38*$scale)) -Format $format + } + else { + Draw-CenteredText -Graphics $graphics -Text $locationPrimaryText -Font $locationFont ` + -Brush $accentBrush -Bounds ([Drawing.RectangleF]::new($panelX + 60*$scale, $panelY + 195*$scale, $panelWidth - 120*$scale, 78*$scale)) -Format $format + } } finally { $format.Dispose() + $locationSecondaryFont.Dispose() $locationFont.Dispose() $nameFont.Dispose() $welcomeFont.Dispose() @@ -519,6 +545,8 @@ Write-WelcomeLog -Message ("OK computer={0}; gender={1}; location={2}; ou={3}; o Gender = $Gender WelcomeHeading = $welcomeHeading LocationText = $locationText + LocationPrimaryText = $locationPrimaryText + LocationSecondaryText = $locationSecondaryText OutputPath = $OutputPath Applied = -not $SkipApply } diff --git a/scripts/Set-SguWelcomeWallpaper.sh b/scripts/Set-SguWelcomeWallpaper.sh index 3077c51..b2ecccc 100644 --- a/scripts/Set-SguWelcomeWallpaper.sh +++ b/scripts/Set-SguWelcomeWallpaper.sh @@ -129,8 +129,8 @@ fi article_for() { local value=${1,,} case "$value" in - sala*|aula*|facultad*|unidad*|biblioteca*|oficina*|coordinación*) printf la ;; - laboratorio*|centro*|edificio*|campus*|taller*|auditorio*) printf el ;; + sala*|facultad*|unidad*|biblioteca*|oficina*|coordinación*) printf la ;; + aula*|laboratorio*|centro*|edificio*|campus*|taller*|auditorio*) printf el ;; *) printf '' ;; esac } @@ -159,29 +159,60 @@ case "$gender" in ;; *) welcome_text='Te damos la bienvenida,' - located_text='Ubicación:' + located_text='' engineering_lab_text='Acceso al Laboratorio de Cómputo de Ingeniería.' ;; esac +location_primary='' +location_secondary='' if [[ -n $location && -n $organizational_unit ]]; then - room_phrase=$(with_article "$location") + room_article=$(article_for "$location") + if [[ -n $gender ]]; then + room_phrase=$(with_article "$location") + location_primary="${located_text} ${room_phrase}" + elif [[ $room_article == el ]]; then + location_primary="Acceso al ${location}" + elif [[ -n $room_article ]]; then + location_primary="Acceso a ${room_article} ${location}" + else + location_primary="Acceso a ${location}" + fi ou_article=$(article_for "$organizational_unit") if [[ $ou_article == el ]]; then - ou_phrase="del ${organizational_unit}" + location_secondary="del ${organizational_unit}." elif [[ -n $ou_article ]]; then - ou_phrase="de ${ou_article} ${organizational_unit}" + location_secondary="de ${ou_article} ${organizational_unit}." else - ou_phrase="de ${organizational_unit}" + location_secondary="de ${organizational_unit}." fi - location_text="${located_text} ${room_phrase} ${ou_phrase}." elif [[ -n $location ]]; then - location_text="${located_text} $(with_article "$location")." + room_article=$(article_for "$location") + if [[ -n $gender ]]; then + location_primary="${located_text} $(with_article "$location")." + elif [[ $room_article == el ]]; then + location_primary="Acceso al ${location}." + elif [[ -n $room_article ]]; then + location_primary="Acceso a ${room_article} ${location}." + else + location_primary="Acceso a ${location}." + fi elif [[ -n $organizational_unit ]]; then - location_text="${located_text} $(with_article "$organizational_unit")." + ou_article=$(article_for "$organizational_unit") + if [[ -n $gender ]]; then + location_primary="${located_text} $(with_article "$organizational_unit")." + elif [[ $ou_article == el ]]; then + location_primary="Acceso al ${organizational_unit}." + elif [[ -n $ou_article ]]; then + location_primary="Acceso a ${ou_article} ${organizational_unit}." + else + location_primary="Acceso a ${organizational_unit}." + fi else - location_text=$engineering_lab_text + location_primary=$engineering_lab_text fi +location_text=$location_primary +[[ -n $location_secondary ]] && location_text+=$'\n'"$location_secondary" width=1600 height=1000 @@ -202,6 +233,7 @@ scale=$(( height * 100 / 1000 )) welcome_size=$(( 34 * scale / 100 )) name_size=$(( 70 * scale / 100 )) location_size=$(( 27 * scale / 100 )) +location_secondary_size=$(( 20 * scale / 100 )) panel_width=$(( width * 76 / 100 )) panel_height=$(( 310 * scale / 100 )) panel_x1=$(( (width - panel_width) / 2 )) @@ -232,6 +264,17 @@ if [[ $serif_font == DejaVu-Serif ]] && command -v fc-list >/dev/null 2>&1; then fi fi +location_annotations=( + -font "$sans_font" -weight 400 -style Normal -pointsize "$location_size" + -fill '#D3E2FF' -stroke none -annotate "+0+$(( 76 * scale / 100 ))" "$location_primary" +) +if [[ -n $location_secondary ]]; then + location_annotations+=( + -font "$sans_font" -weight 400 -style Normal -pointsize "$location_secondary_size" + -fill '#D3E2FF' -stroke none -annotate "+0+$(( 116 * scale / 100 ))" "$location_secondary" + ) +fi + if ! "${image_command[@]}" "$BASE_IMAGE" \ -resize "${width}x${height}^" -gravity center -extent "${width}x${height}" \ -fill 'rgba(0,13,58,0.30)' -draw "rectangle ${panel_x1},${panel_y1} ${panel_x2},${panel_y2}" \ @@ -241,8 +284,7 @@ if ! "${image_command[@]}" "$BASE_IMAGE" \ -annotate "+0-$(( 92 * scale / 100 ))" "$welcome_text" \ -font "$serif_font" -weight 700 -style Italic -pointsize "$name_size" \ -fill white -annotate "+0-$(( 22 * scale / 100 ))" "$display_name" \ - -font "$sans_font" -weight 400 -style Normal -pointsize "$location_size" \ - -fill '#D3E2FF' -annotate "+0+$(( 88 * scale / 100 ))" "$location_text" \ + "${location_annotations[@]}" \ -quality 94 "$output_path" 2>>"$log_path"; then fail_softly 'ImageMagick could not render the welcome wallpaper.' fi diff --git a/tests/WelcomeWallpaper.Tests.ps1 b/tests/WelcomeWallpaper.Tests.ps1 index 72f9ef8..8f2afc3 100644 --- a/tests/WelcomeWallpaper.Tests.ps1 +++ b/tests/WelcomeWallpaper.Tests.ps1 @@ -89,7 +89,29 @@ Describe 'Welcome wallpaper with AD metadata' { $result = Invoke-WelcomeFixture -DirectoryGender $null ` -DirectoryLocation 'Aula Flexible' ` -DirectoryOu 'Centro de Experiencia Digital' - $result.LocationText | Should Be 'Acceso al Aula Flexible del Centro de Experiencia Digital.' + $result.LocationText | Should Be "Acceso al Aula Flexible`ndel Centro de Experiencia Digital." + $result.LocationPrimaryText | Should Be 'Acceso al Aula Flexible' + $result.LocationSecondaryText | Should Be 'del Centro de Experiencia Digital.' + } + + It 'uses the requested neutral, masculine and feminine location wording' { + $neutral = Invoke-WelcomeFixture -DirectoryGender $null ` + -DirectoryLocation 'Sala de Aplicaciones' ` + -DirectoryOu 'Laboratorio de Cómputo de Ingeniería' + $neutral.LocationPrimaryText | Should Be 'Acceso a la Sala de Aplicaciones' + $neutral.LocationSecondaryText | Should Be 'del Laboratorio de Cómputo de Ingeniería.' + + $male = Invoke-WelcomeFixture -DirectoryGender 'Male' ` + -DirectoryLocation 'Aula Flexible' ` + -DirectoryOu 'Centro de Experiencia Digital' + $male.LocationPrimaryText | Should Be 'Estás ubicado en el Aula Flexible' + $male.LocationSecondaryText | Should Be 'del Centro de Experiencia Digital.' + + $female = Invoke-WelcomeFixture -DirectoryGender 'Female' ` + -DirectoryLocation 'Sala de Redes' ` + -DirectoryOu 'Laboratorio de Cómputo de Ingeniería' + $female.LocationPrimaryText | Should Be 'Estás ubicada en la Sala de Redes' + $female.LocationSecondaryText | Should Be 'del Laboratorio de Cómputo de Ingeniería.' } It 'keeps machine location metadata when the GPO command has no location arguments' { @@ -98,6 +120,26 @@ Describe 'Welcome wallpaper with AD metadata' { -DirectoryOu 'Laboratorio' ` -MachineLocation 'Aula Flexible' ` -MachineOu 'Centro de Experiencia Digital' - $result.LocationText | Should Be 'Acceso al Aula Flexible del Centro de Experiencia Digital.' + $result.LocationText | Should Be "Acceso al Aula Flexible`ndel Centro de Experiencia Digital." + } + + It 'ships the logo inside the base image instead of compositing it at runtime' { + $source | Should Not Match 'lasalle-logo-blanco|DrawImage.*logo|composite.*logo' + $bitmap = [Drawing.Bitmap]::FromFile((Join-Path $repositoryRoot 'assets\branding\darkblue.jpg')) + try { + $whitePixels = 0 + for ($x = 60; $x -lt 390; $x += 2) { + for ($y = 45; $y -lt 175; $y += 2) { + $pixel = $bitmap.GetPixel($x, $y) + if ($pixel.R -gt 220 -and $pixel.G -gt 220 -and $pixel.B -gt 220) { + $whitePixels++ + } + } + } + ($whitePixels -gt 250) | Should Be $true + } + finally { + $bitmap.Dispose() + } } }