From 039c669fc7e16e8a72f1030d2bd816051dccb9c9 Mon Sep 17 00:00:00 2001 From: Lance Pioch Date: Sun, 24 Mar 2024 01:48:21 -0400 Subject: [PATCH 01/40] Customize the domain --- config/panel.php | 2 +- resources/scripts/components/elements/PageContentBlock.tsx | 2 +- resources/views/admin/index.blade.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/panel.php b/config/panel.php index 32f68ccb6..e81ec44a2 100644 --- a/config/panel.php +++ b/config/panel.php @@ -92,7 +92,7 @@ return [ 'cdn' => [ 'cache_time' => 60, - 'url' => 'https://cdn.example.com/releases/latest.json', + 'url' => 'https://cdn.pelican.dev/releases/latest.json', ], /* diff --git a/resources/scripts/components/elements/PageContentBlock.tsx b/resources/scripts/components/elements/PageContentBlock.tsx index 13c787bfa..b070b071c 100644 --- a/resources/scripts/components/elements/PageContentBlock.tsx +++ b/resources/scripts/components/elements/PageContentBlock.tsx @@ -28,7 +28,7 @@ const PageContentBlock: React.FC = ({ title, showFlashKey

diff --git a/resources/views/admin/index.blade.php b/resources/views/admin/index.blade.php index 761b3b68b..99e0dad9b 100644 --- a/resources/views/admin/index.blade.php +++ b/resources/views/admin/index.blade.php @@ -44,7 +44,7 @@

 
From 06f66027dd1f7b8f8e665bfd41cab4464d283775 Mon Sep 17 00:00:00 2001 From: Lance Pioch Date: Sun, 24 Mar 2024 14:43:25 -0400 Subject: [PATCH 02/40] Whoops, add this in real quick before anybody notices! --- .../migrations/2024_03_14_055537_remove_locations_table.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/database/migrations/2024_03_14_055537_remove_locations_table.php b/database/migrations/2024_03_14_055537_remove_locations_table.php index a6e74e8bb..bf41cd464 100644 --- a/database/migrations/2024_03_14_055537_remove_locations_table.php +++ b/database/migrations/2024_03_14_055537_remove_locations_table.php @@ -13,6 +13,7 @@ return new class extends Migration { Schema::table('nodes', function (Blueprint $table) { $table->dropForeign('nodes_location_id_foreign'); + $table->dropColumn('location_id'); }); Schema::drop('locations'); @@ -34,6 +35,11 @@ return new class extends Migration $table->timestamps(); }); + Schema::table('nodes', function (Blueprint $table) { + $table->unsignedInteger('location_id')->default(0); + $table->foreign('location_id')->references('id')->on('locations'); + }); + Schema::table('api_keys', function (Blueprint $table) { $table->unsignedTinyInteger('r_locations')->default(0); }); From a61c07a04ccaac475bfef5d415e27518551f98a8 Mon Sep 17 00:00:00 2001 From: Huguitis Date: Wed, 3 Apr 2024 22:21:25 +0200 Subject: [PATCH 03/40] Create validation.php (Spanish) --- lang/es/validation.php | 106 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 lang/es/validation.php diff --git a/lang/es/validation.php b/lang/es/validation.php new file mode 100644 index 000000000..c5b76a490 --- /dev/null +++ b/lang/es/validation.php @@ -0,0 +1,106 @@ + 'El campo :attribute debe ser aceptado.', + 'active_url' => 'El campo :attribute no es una URL válida.', + 'after' => 'El campo :attribute debe ser una fecha posterior a :date.', + 'after_or_equal' => 'El campo :attribute debe ser una fecha posterior o igual a :date.', + 'alpha' => 'El campo :attribute solo puede contener letras.', + 'alpha_dash' => 'El campo :attribute solo puede contener letras, números y guiones.', + 'alpha_num' => 'El campo :attribute solo puede contener letras y números.', + 'array' => 'El campo :attribute debe ser un conjunto.', + 'before' => 'El campo :attribute debe ser una fecha anterior a :date.', + 'before_or_equal' => 'El campo :attribute debe ser una fecha anterior o igual a :date.', + 'between' => [ + 'numeric' => 'El campo :attribute debe estar entre :min y :max.', + 'file' => 'El campo :attribute debe tener entre :min y :max kilobytes.', + 'string' => 'El campo :attribute debe tener entre :min y :max caracteres.', + 'array' => 'El campo :attribute debe tener entre :min y :max elementos.', + ], + 'boolean' => 'El campo :attribute debe ser verdadero o falso.', + 'confirmed' => 'La confirmación de :attribute no coincide.', + 'date' => 'El campo :attribute no es una fecha válida.', + 'date_format' => 'El campo :attribute no coincide con el formato :format.', + 'different' => 'Los campos :attribute y :other deben ser diferentes.', + 'digits' => 'El campo :attribute debe tener :digits dígitos.', + 'digits_between' => 'El campo :attribute debe tener entre :min y :max dígitos.', + 'dimensions' => 'Las dimensiones de la imagen :attribute no son válidas.', + 'distinct' => 'El campo :attribute tiene un valor duplicado.', + 'email' => 'El campo :attribute debe ser una dirección de correo electrónico válida.', + 'exists' => 'El :attribute seleccionado no es válido.', + 'file' => 'El campo :attribute debe ser un archivo.', + 'filled' => 'El campo :attribute es obligatorio.', + 'image' => 'El campo :attribute debe ser una imagen.', + 'in' => 'El :attribute seleccionado no es válido.', + 'in_array' => 'El campo :attribute no existe en :other.', + 'integer' => 'El campo :attribute debe ser un número entero.', + 'ip' => 'El campo :attribute debe ser una dirección IP válida.', + 'json' => 'El campo :attribute debe ser una cadena JSON válida.', + 'max' => [ + 'numeric' => 'El campo :attribute no debe ser mayor que :max.', + 'file' => 'El tamaño del archivo :attribute no debe ser mayor que :max kilobytes.', + 'string' => 'El campo :attribute no debe contener más de :max caracteres.', + 'array' => 'El campo :attribute no debe contener más de :max elementos.', + ], + 'mimes' => 'El campo :attribute debe ser un archivo del tipo: :values.', + 'mimetypes' => 'El campo :attribute debe ser un archivo del tipo: :values.', + 'min' => [ + 'numeric' => 'El campo :attribute debe tener al menos :min.', + 'file' => 'El tamaño del archivo :attribute debe ser al menos :min kilobytes.', + 'string' => 'El campo :attribute debe tener al menos :min caracteres.', + 'array' => 'El campo :attribute debe tener al menos :min elementos.', + ], + 'not_in' => 'El campo :attribute seleccionado no es válido.', + 'numeric' => 'El campo :attribute debe ser un número.', + 'present' => 'El campo :attribute debe estar presente.', + 'regex' => 'El formato del campo :attribute no es válido.', + 'required' => 'El campo :attribute es obligatorio.', + 'required_if' => 'El campo :attribute es obligatorio cuando :other es :value.', + 'required_unless' => 'El campo :attribute es obligatorio a menos que :other esté en :values.', + 'required_with' => 'El campo :attribute es obligatorio cuando :values está presente.', + 'required_with_all' => 'El campo :attribute es obligatorio cuando :values está presente.', + 'required_without' => 'El campo :attribute es obligatorio cuando :values no está presente.', + 'required_without_all' => 'El campo :attribute es obligatorio cuando ninguno de :values está presente.', + 'same' => 'Los campos :attribute y :other deben coincidir.', + 'size' => [ + 'numeric' => 'El campo :attribute debe ser :size.', + 'file' => 'El campo :attribute debe tener :size kilobytes.', + 'string' => 'El campo :attribute debe tener :size caracteres.', + 'array' => 'El campo :attribute debe contener :size elementos.', + ], + 'string' => 'El campo :attribute debe ser una cadena de texto.', + 'timezone' => 'El campo :attribute debe ser una zona horaria válida.', + 'unique' => 'El valor del campo :attribute ya ha sido tomado.', + 'uploaded' => 'La carga del archivo :attribute ha fallado.', + 'url' => 'El formato de :attribute no es válido.', + + /* + |-------------------------------------------------------------------------- + | Custom Validation Attributes + |-------------------------------------------------------------------------- + | + | The following language lines are used to swap attribute place-holders + | with something more reader friendly such as E-Mail Address instead + | of "email". This simply helps us make messages a little cleaner. + | + */ + + 'attributes' => [], + + // Internal validation logic for Panel + 'internal' => [ + 'variable_value' => 'Variable :env', + 'invalid_password' => 'La contraseña proporcionada no es válida para esta cuenta.', + ], +]; From 9b29ba8e3056fec9108d74a4e8bf05e1574199a7 Mon Sep 17 00:00:00 2001 From: Huguitis Date: Wed, 3 Apr 2024 22:24:15 +0200 Subject: [PATCH 04/40] Create strings.php (Spanish) --- lang/es/strings.php | 95 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 lang/es/strings.php diff --git a/lang/es/strings.php b/lang/es/strings.php new file mode 100644 index 000000000..107d4deb5 --- /dev/null +++ b/lang/es/strings.php @@ -0,0 +1,95 @@ + 'Correo electrónico', + 'email_address' => 'Dirección de correo electrónico', + 'user_identifier' => 'Nombre de usuario o Correo electrónico', + 'password' => 'Contraseña', + 'new_password' => 'Nueva contraseña', + 'confirm_password' => 'Confirmar nueva contraseña', + 'login' => 'Iniciar sesión', + 'home' => 'Inicio', + 'servers' => 'Servidores', + 'id' => 'ID', + 'name' => 'Nombre', + 'node' => 'Nodo', + 'connection' => 'Conexión', + 'memory' => 'Memoria', + 'cpu' => 'CPU', + 'disk' => 'Disco', + 'status' => 'Estado', + 'search' => 'Buscar', + 'suspended' => 'Suspendido', + 'account' => 'Cuenta', + 'security' => 'Seguridad', + 'ip' => 'Dirección IP', + 'last_activity' => 'Última Actividad', + 'revoke' => 'Revocar', + '2fa_token' => 'Token de Autenticación', + 'submit' => 'Enviar', + 'close' => 'Cerrar', + 'settings' => 'Ajustes', + 'configuration' => 'Configuración', + 'sftp' => 'SFTP', + 'databases' => 'Bases de Datos', + 'memo' => 'Nota', + 'created' => 'Creado', + 'expires' => 'Caduca', + 'public_key' => 'Token', + 'api_access' => 'Acceso API', + 'never' => 'nunca', + 'sign_out' => 'Cerrar sesión', + 'admin_control' => 'Control de Administrador', + 'required' => 'Requerido', + 'port' => 'Puerto', + 'username' => 'Nombre de usuario', + 'database' => 'Base de datos', + 'new' => 'Nuevo', + 'danger' => 'Peligro', + 'create' => 'Crear', + 'select_all' => 'Seleccionar Todo', + 'select_none' => 'Seleccionar Ninguno', + 'alias' => 'Alias', + 'primary' => 'Principal', + 'make_primary' => 'Hacer Principal', + 'none' => 'Ninguno', + 'cancel' => 'Cancelar', + 'created_at' => 'Creado en', + 'action' => 'Acción', + 'data' => 'Datos', + 'queued' => 'En cola', + 'last_run' => 'Última Ejecución', + 'next_run' => 'Próxima Ejecución', + 'not_run_yet' => 'Todavía no se ha ejecutado', + 'yes' => 'Sí', + 'no' => 'No', + 'delete' => 'Eliminar', + '2fa' => '2FA', + 'logout' => 'Cerrar sesión', + 'admin_cp' => 'Panel de Control de Administrador', + 'optional' => 'Opcional', + 'read_only' => 'Solo Lectura', + 'relation' => 'Relación', + 'owner' => 'Propietario', + 'admin' => 'Administrador', + 'subuser' => 'Subusuario', + 'captcha_invalid' => 'El captcha proporcionado no es válido.', + 'tasks' => 'Tareas', + 'seconds' => 'Segundos', + 'minutes' => 'Minutos', + 'under_maintenance' => 'En Mantenimiento', + 'days' => [ + 'sun' => 'Domingo', + 'mon' => 'Lunes', + 'tues' => 'Martes', + 'wed' => 'Miércoles', + 'thurs' => 'Jueves', + 'fri' => 'Viernes', + 'sat' => 'Sábado', + ], + 'last_used' => 'Último Uso', + 'enable' => 'Activar', + 'disable' => 'Desactivar', + 'save' => 'Guardar', + 'copyright' => '® 2024 - :year Pelican', +]; From 79e8842228425c4d80c4027ca6c5219f48928f47 Mon Sep 17 00:00:00 2001 From: Huguitis Date: Wed, 3 Apr 2024 22:24:58 +0200 Subject: [PATCH 05/40] Create passwords.php (Spanish) --- lang/es/passwords.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 lang/es/passwords.php diff --git a/lang/es/passwords.php b/lang/es/passwords.php new file mode 100644 index 000000000..293dbaab2 --- /dev/null +++ b/lang/es/passwords.php @@ -0,0 +1,19 @@ + 'Las contraseñas deben tener al menos seis caracteres y coincidir con la confirmación.', + 'reset' => '¡Tu contraseña ha sido restablecida!', + 'sent' => '¡Hemos enviado por correo electrónico el enlace para restablecer tu contraseña!', + 'token' => 'Este token de restablecimiento de contraseña no es válido.', + 'user' => "No podemos encontrar un usuario con esa dirección de correo electrónico.", +]; From f805219ddcf1ae41db3a3215691b084da8318b6f Mon Sep 17 00:00:00 2001 From: Huguitis Date: Wed, 3 Apr 2024 22:25:37 +0200 Subject: [PATCH 06/40] Create pagination.php (Spanish) --- lang/es/pagination.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 lang/es/pagination.php diff --git a/lang/es/pagination.php b/lang/es/pagination.php new file mode 100644 index 000000000..51862f2eb --- /dev/null +++ b/lang/es/pagination.php @@ -0,0 +1,17 @@ + '« Anterior', + 'next' => 'Siguiente »', +]; From 2225d50b9a1ba4f90aee8264acac33fe0e403748 Mon Sep 17 00:00:00 2001 From: Huguitis Date: Wed, 3 Apr 2024 22:27:34 +0200 Subject: [PATCH 07/40] Create exceptions.php (Spanish) --- lang/es/exceptions.php | 55 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 lang/es/exceptions.php diff --git a/lang/es/exceptions.php b/lang/es/exceptions.php new file mode 100644 index 000000000..14ebcfb85 --- /dev/null +++ b/lang/es/exceptions.php @@ -0,0 +1,55 @@ + 'Se produjo una excepción al intentar comunicarse con el daemon, lo que resultó en un código de respuesta HTTP/:code. Esta excepción ha sido registrada.', + 'node' => [ + 'servers_attached' => 'Un nodo no debe tener servidores vinculados a él para poder ser eliminado.', + 'daemon_off_config_updated' => 'La configuración del daemon se ha actualizado, sin embargo, se encontró un error al intentar actualizar automáticamente el archivo de configuración en el daemon. Deberás actualizar manualmente el archivo de configuración (config.yml) para que el daemon aplique estos cambios.', + ], + 'allocations' => [ + 'server_using' => 'Actualmente hay un servidor asignado a esta asignación. Una asignación solo puede ser eliminada si ningún servidor está asignado actualmente.', + 'too_many_ports' => 'Agregar más de 1000 puertos en un solo rango a la vez no está soportado.', + 'invalid_mapping' => 'El mapeo proporcionado para el puerto :port era inválido y no pudo ser procesado.', + 'cidr_out_of_range' => 'La notación CIDR solo permite máscaras entre /25 y /32.', + 'port_out_of_range' => 'Los puertos en una asignación deben ser mayores que 1024 y menores o iguales a 65535.', + ], + 'egg' => [ + 'delete_has_servers' => 'Un Huevo con servidores activos vinculados a él no puede ser eliminado del Panel.', + 'invalid_copy_id' => 'El Huevo seleccionado para copiar un script desde no existe o está copiando un script en sí mismo.', + 'has_children' => 'Este Huevo es padre de uno o más otros Huevos. Por favor, elimina esos Huevos antes de eliminar este Huevo.', + ], + 'variables' => [ + 'env_not_unique' => 'La variable de entorno :name debe ser única para este Huevo.', + 'reserved_name' => 'La variable de entorno :name está protegida y no se puede asignar a una variable.', + 'bad_validation_rule' => 'La regla de validación ":rule" no es una regla válida para esta aplicación.', + ], + 'importer' => [ + 'json_error' => 'Hubo un error al intentar analizar el archivo JSON: :error.', + 'file_error' => 'El archivo JSON proporcionado no era válido.', + 'invalid_json_provided' => 'El archivo JSON proporcionado no está en un formato que pueda ser reconocido.', + ], + 'subusers' => [ + 'editing_self' => 'No está permitido editar tu propia cuenta de subusuario.', + 'user_is_owner' => 'No puedes agregar al propietario del servidor como subusuario para este servidor.', + 'subuser_exists' => 'Ya hay un usuario con esa dirección de correo electrónico asignado como subusuario para este servidor.', + ], + 'databases' => [ + 'delete_has_databases' => 'No se puede eliminar un servidor de host de base de datos que tiene bases de datos activas vinculadas a él.', + ], + 'tasks' => [ + 'chain_interval_too_long' => 'El tiempo máximo de intervalo para una tarea encadenada es de 15 minutos.', + ], + 'locations' => [ + 'has_nodes' => 'No se puede eliminar una ubicación que tiene nodos activos vinculados a ella.', + ], + 'users' => [ + 'node_revocation_failed' => 'Error al revocar las claves en Nodo #:node. :error', + ], + 'deployment' => [ + 'no_viable_nodes' => 'No se encontraron nodos que satisfagan los requisitos especificados para el despliegue automático.', + 'no_viable_allocations' => 'No se encontraron asignaciones que satisfagan los requisitos para el despliegue automático.', + ], + 'api' => [ + 'resource_not_found' => 'El recurso solicitado no existe en este servidor.', + ], +]; From 9120e81514a52d1aa44a92143723d45a1ba1fb4a Mon Sep 17 00:00:00 2001 From: Huguitis Date: Wed, 3 Apr 2024 22:28:25 +0200 Subject: [PATCH 08/40] Create auth.php (Spanish) --- lang/es/auth.php | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 lang/es/auth.php diff --git a/lang/es/auth.php b/lang/es/auth.php new file mode 100644 index 000000000..a3c86efb4 --- /dev/null +++ b/lang/es/auth.php @@ -0,0 +1,27 @@ + 'Iniciar sesión', + 'go_to_login' => 'Ir al inicio de sesión', + 'failed' => 'No se pudo encontrar ninguna cuenta que coincida con esas credenciales.', + + 'forgot_password' => [ + 'label' => '¿Olvidaste tu contraseña?', + 'label_help' => 'Ingresa la dirección de correo electrónico de tu cuenta para recibir instrucciones sobre cómo restablecer tu contraseña.', + 'button' => 'Recuperar cuenta', + ], + + 'reset_password' => [ + 'button' => 'Restablecer e iniciar sesión', + ], + + 'two_factor' => [ + 'label' => 'Token de 2 Factores', + 'label_help' => 'Esta cuenta requiere un segundo nivel de autenticación para continuar. Por favor, ingresa el código generado por tu dispositivo para completar este inicio de sesión.', + 'checkpoint_failed' => 'El token de autenticación de dos factores no era válido.', + ], + + 'throttle' => 'Demasiados intentos de inicio de sesión. Por favor, inténtalo de nuevo en :seconds segundos.', + 'password_requirements' => 'La contraseña debe tener al menos 8 caracteres de longitud y debe ser única para este sitio.', + '2fa_must_be_enabled' => 'El administrador ha requerido que la Autenticación de 2 Factores esté habilitada para tu cuenta para poder usar el Panel.', +]; From 20875d8d3fec9302753b91a328d7c34c44aa6b15 Mon Sep 17 00:00:00 2001 From: Huguitis Date: Wed, 3 Apr 2024 22:30:21 +0200 Subject: [PATCH 09/40] Create activity.php (Spanish) --- lang/es/activity.php | 130 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 lang/es/activity.php diff --git a/lang/es/activity.php b/lang/es/activity.php new file mode 100644 index 000000000..68f9fa468 --- /dev/null +++ b/lang/es/activity.php @@ -0,0 +1,130 @@ + [ + 'fail' => 'Inicio de sesión fallido', + 'success' => 'Sesión iniciada', + 'password-reset' => 'Restablecimiento de contraseña', + 'reset-password' => 'Solicitud de restablecimiento de contraseña', + 'checkpoint' => 'Solicitud de autenticación de dos factores', + 'recovery-token' => 'Token de recuperación de dos factores utilizado', + 'token' => 'Resuelto desafío de dos factores', + 'ip-blocked' => 'Solicitud bloqueada desde la dirección IP no listada para :identifier', + 'sftp' => [ + 'fail' => 'Inicio de sesión SFTP fallido', + ], + ], + 'user' => [ + 'account' => [ + 'email-changed' => 'Cambio de correo electrónico de :old a :new', + 'password-changed' => 'Contraseña cambiada', + ], + 'api-key' => [ + 'create' => 'Se creó una nueva clave API :identifier', + 'delete' => 'Se eliminó la clave API :identifier', + ], + 'ssh-key' => [ + 'create' => 'Se agregó la clave SSH :fingerprint a la cuenta', + 'delete' => 'Se eliminó la clave SSH :fingerprint de la cuenta', + ], + 'two-factor' => [ + 'create' => 'Se habilitó la autenticación de dos factores', + 'delete' => 'Se deshabilitó la autenticación de dos factores', + ], + ], + 'server' => [ + 'reinstall' => 'Servidor reinstalado', + 'console' => [ + 'command' => 'Ejecutado ":command" en el servidor', + ], + 'power' => [ + 'start' => 'Iniciado el servidor', + 'stop' => 'Detenido el servidor', + 'restart' => 'Reiniciado el servidor', + 'kill' => 'Finalizado el proceso del servidor', + ], + 'backup' => [ + 'download' => 'Descargada la copia de seguridad :name', + 'delete' => 'Eliminada la copia de seguridad :name', + 'restore' => 'Restaurada la copia de seguridad :name (archivos eliminados: :truncate)', + 'restore-complete' => 'Restauración completa de la copia de seguridad :name', + 'restore-failed' => 'Falló la restauración de la copia de seguridad :name', + 'start' => 'Iniciada una nueva copia de seguridad :name', + 'complete' => 'Marcada la copia de seguridad :name como completada', + 'fail' => 'Marcada la copia de seguridad :name como fallida', + 'lock' => 'Bloqueada la copia de seguridad :name', + 'unlock' => 'Desbloqueada la copia de seguridad :name', + ], + 'database' => [ + 'create' => 'Creada nueva base de datos :name', + 'rotate-password' => 'Contraseña rotada para la base de datos :name', + 'delete' => 'Eliminada la base de datos :name', + ], + 'file' => [ + 'compress_one' => 'Comprimido :directory:file', + 'compress_other' => 'Comprimidos :count archivos en :directory', + 'read' => 'Visto el contenido de :file', + 'copy' => 'Creada una copia de :file', + 'create-directory' => 'Creado directorio :directory:name', + 'decompress' => 'Descomprimidos :files en :directory', + 'delete_one' => 'Eliminado :directory:files.0', + 'delete_other' => 'Eliminados :count archivos en :directory', + 'download' => 'Descargado :file', + 'pull' => 'Descargado un archivo remoto desde :url a :directory', + 'rename_one' => 'Renombrado :directory:files.0.from a :directory:files.0.to', + 'rename_other' => 'Renombrados :count archivos en :directory', + 'write' => 'Escrito nuevo contenido en :file', + 'upload' => 'Iniciada una carga de archivo', + 'uploaded' => 'Cargado :directory:file', + ], + 'sftp' => [ + 'denied' => 'Acceso SFTP bloqueado debido a permisos', + 'create_one' => 'Creado :files.0', + 'create_other' => 'Creados :count nuevos archivos', + 'write_one' => 'Modificado el contenido de :files.0', + 'write_other' => 'Modificado el contenido de :count archivos', + 'delete_one' => 'Eliminado :files.0', + 'delete_other' => 'Eliminados :count archivos', + 'create-directory_one' => 'Creado el directorio :files.0', + 'create-directory_other' => 'Creados :count directorios', + 'rename_one' => 'Renombrado :files.0.from a :files.0.to', + 'rename_other' => 'Renombrados o movidos :count archivos', + ], + 'allocation' => [ + 'create' => 'Añadida :allocation al servidor', + 'notes' => 'Actualizadas las notas para :allocation de ":old" a ":new"', + 'primary' => 'Establecida :allocation como la asignación primaria del servidor', + 'delete' => 'Eliminada la asignación :allocation', + ], + 'schedule' => [ + 'create' => 'Creado el horario :name', + 'update' => 'Actualizado el horario :name', + 'execute' => 'Ejecutado manualmente el horario :name', + 'delete' => 'Eliminado el horario :name', + ], + 'task' => [ + 'create' => 'Creada una nueva tarea ":action" para el horario :name', + 'update' => 'Actualizada la tarea ":action" para el horario :name', + 'delete' => 'Eliminada una tarea para el horario :name', + ], + 'settings' => [ + 'rename' => 'Renombrado el servidor de :old a :new', + 'description' => 'Cambiada la descripción del servidor de :old a :new', + ], + 'startup' => [ + 'edit' => 'Cambiada la variable :variable de ":old" a ":new"', + 'image' => 'Actualizada la imagen de Docker del servidor de :old a :new', + ], + 'subuser' => [ + 'create' => 'Añadido :email como subusuario', + 'update' => 'Actualizados los permisos del subusuario :email', + 'delete' => 'Eliminado :email como subusuario', + ], + ], +]; From 4c4ec549815e6d754f40db84513605467416d893 Mon Sep 17 00:00:00 2001 From: Huguitis Date: Wed, 3 Apr 2024 22:31:29 +0200 Subject: [PATCH 10/40] Create users.php (Spanish) --- lang/es/server/users.php | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 lang/es/server/users.php diff --git a/lang/es/server/users.php b/lang/es/server/users.php new file mode 100644 index 000000000..b71f9389a --- /dev/null +++ b/lang/es/server/users.php @@ -0,0 +1,33 @@ + [ + 'websocket_*' => 'Permite el acceso al websocket para este servidor.', + 'control_console' => 'Permite al usuario enviar datos a la consola del servidor.', + 'control_start' => 'Permite al usuario iniciar la instancia del servidor.', + 'control_stop' => 'Permite al usuario detener la instancia del servidor.', + 'control_restart' => 'Permite al usuario reiniciar la instancia del servidor.', + 'control_kill' => 'Permite al usuario eliminar la instancia del servidor.', + 'user_create' => 'Permite al usuario crear nuevas cuentas de usuario para el servidor.', + 'user_read' => 'Permite al usuario ver los usuarios asociados con este servidor.', + 'user_update' => 'Permite al usuario modificar otros usuarios asociados con este servidor.', + 'user_delete' => 'Permite al usuario eliminar otros usuarios asociados con este servidor.', + 'file_create' => 'Permite al usuario crear nuevos archivos y directorios.', + 'file_read' => 'Permite al usuario ver archivos y carpetas asociados con esta instancia de servidor, así como ver su contenido.', + 'file_update' => 'Permite al usuario actualizar archivos y carpetas asociados con el servidor.', + 'file_delete' => 'Permite al usuario eliminar archivos y directorios.', + 'file_archive' => 'Permite al usuario crear archivos de archivos y descomprimir archivos existentes.', + 'file_sftp' => 'Permite al usuario realizar las acciones de archivo anteriores utilizando un cliente SFTP.', + 'allocation_read' => 'Permite el acceso a las páginas de gestión de asignación del servidor.', + 'allocation_update' => 'Permite al usuario realizar modificaciones en las asignaciones del servidor.', + 'database_create' => 'Permite al usuario crear una nueva base de datos para el servidor.', + 'database_read' => 'Permite al usuario ver las bases de datos del servidor.', + 'database_update' => 'Permite al usuario realizar modificaciones en una base de datos. Si el usuario no tiene también el permiso de "Ver contraseña", no podrá modificar la contraseña.', + 'database_delete' => 'Permite al usuario eliminar una instancia de base de datos.', + 'database_view_password' => 'Permite al usuario ver la contraseña de una base de datos en el sistema.', + 'schedule_create' => 'Permite al usuario crear un nuevo horario para el servidor.', + 'schedule_read' => 'Permite al usuario ver los horarios de un servidor.', + 'schedule_update' => 'Permite al usuario realizar modificaciones en un horario existente del servidor.', + 'schedule_delete' => 'Permite al usuario eliminar un horario del servidor.', + ], +]; From 43a250ac31526fd4e2f4b4a56ac6d9a1f12b314d Mon Sep 17 00:00:00 2001 From: Huguitis Date: Wed, 3 Apr 2024 22:32:32 +0200 Subject: [PATCH 11/40] Create index.php (Spanish) --- lang/es/dashboard/index.php | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 lang/es/dashboard/index.php diff --git a/lang/es/dashboard/index.php b/lang/es/dashboard/index.php new file mode 100644 index 000000000..ccbdd18f2 --- /dev/null +++ b/lang/es/dashboard/index.php @@ -0,0 +1,8 @@ + 'Buscar servidores...', + 'no_matches' => 'No se encontraron servidores que coincidan con los criterios de búsqueda proporcionados.', + 'cpu_title' => 'CPU', + 'memory_title' => 'Memoria', +]; From c328f5cd9bef85fee84534bab8e2ffcbac464b0e Mon Sep 17 00:00:00 2001 From: Huguitis Date: Wed, 3 Apr 2024 22:33:19 +0200 Subject: [PATCH 12/40] Create account.php (Spanish) --- lang/es/dashboard/account.php | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 lang/es/dashboard/account.php diff --git a/lang/es/dashboard/account.php b/lang/es/dashboard/account.php new file mode 100644 index 000000000..df74c95d9 --- /dev/null +++ b/lang/es/dashboard/account.php @@ -0,0 +1,28 @@ + [ + 'title' => 'Actualizar tu correo electrónico', + 'updated' => 'Tu dirección de correo electrónico ha sido actualizada.', + ], + 'password' => [ + 'title' => 'Cambiar tu contraseña', + 'requirements' => 'Tu nueva contraseña debe tener al menos 8 caracteres de longitud.', + 'updated' => 'Tu contraseña ha sido actualizada.', + ], + 'two_factor' => [ + 'button' => 'Configurar autenticación de 2 factores', + 'disabled' => 'La autenticación de dos factores ha sido desactivada en tu cuenta. Ya no se te pedirá que proporciones un token al iniciar sesión.', + 'enabled' => '¡La autenticación de dos factores ha sido activada en tu cuenta! A partir de ahora, al iniciar sesión, se te pedirá que proporciones el código generado por tu dispositivo.', + 'invalid' => 'El token proporcionado no era válido.', + 'setup' => [ + 'title' => 'Configurar autenticación de dos factores', + 'help' => '¿No puedes escanear el código? Ingresa el código a continuación en tu aplicación:', + 'field' => 'Introduce el token', + ], + 'disable' => [ + 'title' => 'Desactivar autenticación de dos factores', + 'field' => 'Introduce el token', + ], + ], +]; From 5d4713e0debd3fb5393910c0f1ba538887289b42 Mon Sep 17 00:00:00 2001 From: Huguitis Date: Wed, 3 Apr 2024 22:34:27 +0200 Subject: [PATCH 13/40] Create messages.php (Spanish) --- lang/es/command/messages.php | 59 ++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 lang/es/command/messages.php diff --git a/lang/es/command/messages.php b/lang/es/command/messages.php new file mode 100644 index 000000000..168d05b26 --- /dev/null +++ b/lang/es/command/messages.php @@ -0,0 +1,59 @@ + [ + 'search_users' => 'Introduce un nombre de usuario, ID de usuario o dirección de correo electrónico', + 'select_search_user' => 'ID del usuario a eliminar (Introduce \'0\' para volver a buscar)', + 'deleted' => 'Usuario eliminado correctamente del Panel.', + 'confirm_delete' => '¿Estás seguro de que quieres eliminar este usuario del Panel?', + 'no_users_found' => 'No se encontraron usuarios para el término de búsqueda proporcionado.', + 'multiple_found' => 'Se encontraron varias cuentas para el usuario proporcionado, no se puede eliminar un usuario debido a la bandera --no-interaction.', + 'ask_admin' => '¿Es este usuario un administrador?', + 'ask_email' => 'Dirección de correo electrónico', + 'ask_username' => 'Nombre de usuario', + 'ask_name_first' => 'Nombre', + 'ask_name_last' => 'Apellido', + 'ask_password' => 'Contraseña', + 'ask_password_tip' => 'Si deseas crear una cuenta con una contraseña aleatoria enviada por correo electrónico al usuario, vuelve a ejecutar este comando (CTRL+C) y pasa la bandera `--no-password`.', + 'ask_password_help' => 'Las contraseñas deben tener al menos 8 caracteres de longitud y contener al menos una letra mayúscula y un número.', + '2fa_help_text' => [ + 'Este comando deshabilitará la autenticación de dos factores para la cuenta de un usuario si está habilitada. Esto solo debe usarse como un comando de recuperación de cuenta si el usuario está bloqueado fuera de su cuenta.', + 'Si esto no es lo que querías hacer, presiona CTRL+C para salir de este proceso.', + ], + '2fa_disabled' => 'La autenticación de dos factores ha sido desactivada para :email.', +], +'schedule' => [ + 'output_line' => 'Enviando trabajo para la primera tarea en `:schedule` (:hash).', +], +'maintenance' => [ + 'deleting_service_backup' => 'Eliminando archivo de copia de seguridad del servicio :file.', +], +'server' => [ + 'rebuild_failed' => 'La solicitud de reconstrucción para ":name" (#:id) en el nodo ":node" falló con el error: :message', + 'reinstall' => [ + 'failed' => 'La solicitud de reinstalación para ":name" (#:id) en el nodo ":node" falló con el error: :message', + 'confirm' => 'Estás a punto de reinstalar contra un grupo de servidores. ¿Deseas continuar?', + ], + 'power' => [ + 'confirm' => 'Estás a punto de realizar una :action contra :count servidores. ¿Deseas continuar?', + 'action_failed' => 'La acción de energía para ":name" (#:id) en el nodo ":node" falló con el error: :message', + ], +], +'environment' => [ + 'mail' => [ + 'ask_smtp_host' => 'Host SMTP (por ejemplo, smtp.gmail.com)', + 'ask_smtp_port' => 'Puerto SMTP', + 'ask_smtp_username' => 'Nombre de usuario SMTP', + 'ask_smtp_password' => 'Contraseña SMTP', + 'ask_mailgun_domain' => 'Dominio de Mailgun', + 'ask_mailgun_endpoint' => 'Extremo de Mailgun', + 'ask_mailgun_secret' => 'Secreto de Mailgun', + 'ask_mandrill_secret' => 'Secreto de Mandrill', + 'ask_postmark_username' => 'Clave API de Postmark', + 'ask_driver' => '¿Qué controlador debe usarse para enviar correos electrónicos?', + 'ask_mail_from' => 'Dirección de correo electrónico desde la cual deben originarse los correos electrónicos', + 'ask_mail_name' => 'Nombre que debe aparecer en los correos electrónicos', + 'ask_encryption' => 'Método de cifrado a utilizar', + ], + ], +]; From 0213e7dfec8c8ea3570f2c7959d78f2c072ffc55 Mon Sep 17 00:00:00 2001 From: Huguitis Date: Wed, 3 Apr 2024 22:36:07 +0200 Subject: [PATCH 14/40] Create eggs.php (Spanish) --- lang/es/admin/eggs.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 lang/es/admin/eggs.php diff --git a/lang/es/admin/eggs.php b/lang/es/admin/eggs.php new file mode 100644 index 000000000..ebb5c948c --- /dev/null +++ b/lang/es/admin/eggs.php @@ -0,0 +1,19 @@ + [ + 'imported' => 'El Egg y sus variables asociadas se importaron correctamente.', + 'updated_via_import' => 'Este Egg se ha actualizado utilizando el archivo proporcionado.', + 'deleted' => 'Se eliminó correctamente el Egg solicitado del Panel.', + 'updated' => 'La configuración del Egg se ha actualizado correctamente.', + 'script_updated' => 'El script de instalación del Egg se ha actualizado y se ejecutará cada vez que se instalen servidores.', + 'egg_created' => 'Se ha creado un nuevo Egg correctamente. Deberás reiniciar cualquier daemon en ejecución para aplicar este nuevo Egg.', + ], + 'variables' => [ + 'notices' => [ + 'variable_deleted' => 'La variable ":variable" se ha eliminado y ya no estará disponible para los servidores una vez reconstruidos.', + 'variable_updated' => 'La variable ":variable" se ha actualizado. Deberás reconstruir cualquier servidor que utilice esta variable para aplicar los cambios.', + 'variable_created' => 'Se ha creado correctamente una nueva variable y se ha asignado a este Egg.', + ], + ], +]; From c07f015ccdfaf637daf3f63c25100c3d96ee8646 Mon Sep 17 00:00:00 2001 From: Huguitis Date: Wed, 3 Apr 2024 22:36:49 +0200 Subject: [PATCH 15/40] Create node.php (Spanish) --- lang/es/admin/node.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 lang/es/admin/node.php diff --git a/lang/es/admin/node.php b/lang/es/admin/node.php new file mode 100644 index 000000000..95556057b --- /dev/null +++ b/lang/es/admin/node.php @@ -0,0 +1,15 @@ + [ + 'fqdn_not_resolvable' => 'El FQDN o la dirección IP proporcionada no se resuelve a una dirección IP válida.', + 'fqdn_required_for_ssl' => 'Se requiere un nombre de dominio completo que se resuelva a una dirección IP pública para poder utilizar SSL en este nodo.', + ], + 'notices' => [ + 'allocations_added' => 'Se han añadido correctamente las asignaciones a este nodo.', + 'node_deleted' => 'El nodo se ha eliminado correctamente del panel.', + 'node_created' => 'Se ha creado correctamente un nuevo nodo. Puedes configurar automáticamente el daemon en esta máquina visitando la pestaña \'Configuración\'. Antes de poder añadir cualquier servidor, primero debes asignar al menos una dirección IP y puerto.', + 'node_updated' => 'Se ha actualizado la información del nodo. Si se cambiaron ajustes del daemon, necesitarás reiniciarlo para que los cambios surtan efecto.', + 'unallocated_deleted' => 'Se han eliminado todos los puertos no asignados para :ip.', + ], +]; From 1dcb08ccc03b5c444a25a80ef700ea59abcf45ca Mon Sep 17 00:00:00 2001 From: Huguitis Date: Wed, 3 Apr 2024 22:37:30 +0200 Subject: [PATCH 16/40] Create server.php (Spanish) --- lang/es/admin/server.php | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 lang/es/admin/server.php diff --git a/lang/es/admin/server.php b/lang/es/admin/server.php new file mode 100644 index 000000000..38af8b29c --- /dev/null +++ b/lang/es/admin/server.php @@ -0,0 +1,27 @@ + [ + 'no_new_default_allocation' => 'Estás intentando eliminar la asignación predeterminada para este servidor pero no hay una asignación de respaldo para usar.', + 'marked_as_failed' => 'Este servidor fue marcado como que ha fallado en una instalación anterior. El estado actual no se puede cambiar en este estado.', + 'bad_variable' => 'Hubo un error de validación con la variable :name.', + 'daemon_exception' => 'Hubo una excepción al intentar comunicarse con el daemon que resultó en un código de respuesta HTTP/:code. Esta excepción ha sido registrada. (ID de solicitud: :request_id)', + 'default_allocation_not_found' => 'La asignación predeterminada solicitada no se encontró en las asignaciones de este servidor.', + ], + 'alerts' => [ + 'startup_changed' => 'La configuración de inicio de este servidor se ha actualizado. Si se cambió el huevo de este servidor, se iniciará una reinstalación ahora.', + 'server_deleted' => 'El servidor se ha eliminado correctamente del sistema.', + 'server_created' => 'El servidor se ha creado correctamente en el panel. Por favor, permite al daemon unos minutos para instalar completamente este servidor.', + 'build_updated' => 'Los detalles de construcción para este servidor se han actualizado. Algunos cambios pueden requerir un reinicio para surtir efecto.', + 'suspension_toggled' => 'El estado de suspensión del servidor se ha cambiado a :status.', + 'rebuild_on_boot' => 'Este servidor se ha marcado como que requiere una reconstrucción del contenedor Docker. Esto ocurrirá la próxima vez que se inicie el servidor.', + 'install_toggled' => 'El estado de instalación para este servidor se ha cambiado.', + 'server_reinstalled' => 'Este servidor ha sido encolado para una reinstalación que comienza ahora.', + 'details_updated' => 'Los detalles del servidor se han actualizado correctamente.', + 'docker_image_updated' => 'Se cambió con éxito la imagen Docker predeterminada para usar en este servidor. Se requiere un reinicio para aplicar este cambio.', + 'node_required' => 'Debes tener al menos un nodo configurado antes de poder añadir un servidor a este panel.', + 'transfer_nodes_required' => 'Debes tener al menos dos nodos configurados antes de poder transferir servidores.', + 'transfer_started' => 'La transferencia del servidor se ha iniciado.', + 'transfer_not_viable' => 'El nodo que seleccionaste no tiene el espacio en disco o la memoria disponible requerida para acomodar este servidor.', + ], +]; From 2849f8a36a47d115ef967c8cbeb9255bc78aa5ae Mon Sep 17 00:00:00 2001 From: Huguitis Date: Wed, 3 Apr 2024 22:38:00 +0200 Subject: [PATCH 17/40] Create user.php (Spanish) --- lang/es/admin/user.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 lang/es/admin/user.php diff --git a/lang/es/admin/user.php b/lang/es/admin/user.php new file mode 100644 index 000000000..ab4373270 --- /dev/null +++ b/lang/es/admin/user.php @@ -0,0 +1,12 @@ + [ + 'user_has_servers' => 'No se puede eliminar un usuario con servidores activos asociados a su cuenta. Por favor, elimina sus servidores antes de continuar.', + 'user_is_self' => 'No se puede eliminar tu propia cuenta de usuario.', + ], + 'notices' => [ + 'account_created' => 'La cuenta se ha creado correctamente.', + 'account_updated' => 'La cuenta se ha actualizado correctamente.', + ], +]; From 2e3d17b94a2fdccedac3b895eb2ffd12af2ffd80 Mon Sep 17 00:00:00 2001 From: Lance Pioch Date: Sat, 6 Apr 2024 10:17:17 -0400 Subject: [PATCH 18/40] Redis is no longer the default --- .env.example | 4 ++-- .../Environment/AppSettingsCommand.php | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.env.example b/.env.example index c979b4e52..3db40f368 100644 --- a/.env.example +++ b/.env.example @@ -23,7 +23,7 @@ REDIS_PASSWORD=null REDIS_PORT=6379 CACHE_STORE=file -QUEUE_CONNECTION=redis +QUEUE_CONNECTION=sync SESSION_DRIVER=file HASHIDS_SALT= @@ -36,7 +36,7 @@ MAIL_USERNAME= MAIL_PASSWORD= MAIL_ENCRYPTION=tls MAIL_FROM_ADDRESS=no-reply@example.com -MAIL_FROM_NAME="Panel Administrator" +MAIL_FROM_NAME="Pelican Admin" # Set this to your domain to prevent it defaulting to 'localhost', causing mail servers such as Gmail to reject your mail # MAIL_EHLO_DOMAIN=panel.example.com SESSION_ENCRYPT=false diff --git a/app/Console/Commands/Environment/AppSettingsCommand.php b/app/Console/Commands/Environment/AppSettingsCommand.php index 343130168..c1f857f4e 100644 --- a/app/Console/Commands/Environment/AppSettingsCommand.php +++ b/app/Console/Commands/Environment/AppSettingsCommand.php @@ -11,23 +11,23 @@ class AppSettingsCommand extends Command use EnvironmentWriterTrait; public const CACHE_DRIVERS = [ - 'redis' => 'Redis (recommended)', + 'redis' => 'Redis', 'memcached' => 'Memcached', - 'file' => 'Filesystem', + 'file' => 'Filesystem (recommended)', ]; public const SESSION_DRIVERS = [ - 'redis' => 'Redis (recommended)', + 'redis' => 'Redis', 'memcached' => 'Memcached', 'database' => 'MySQL Database', - 'file' => 'Filesystem', + 'file' => 'Filesystem (recommended)', 'cookie' => 'Cookie', ]; public const QUEUE_DRIVERS = [ - 'redis' => 'Redis (recommended)', + 'redis' => 'Redis', 'database' => 'MySQL Database', - 'sync' => 'Sync', + 'sync' => 'Sync (recommended)', ]; protected $description = 'Configure basic environment settings for the Panel.'; @@ -91,21 +91,21 @@ class AppSettingsCommand extends Command config('app.timezone') ); - $selected = config('cache.default', 'redis'); + $selected = config('cache.default', 'file'); $this->variables['CACHE_STORE'] = $this->option('cache') ?? $this->choice( 'Cache Driver', self::CACHE_DRIVERS, array_key_exists($selected, self::CACHE_DRIVERS) ? $selected : null ); - $selected = config('session.driver', 'redis'); + $selected = config('session.driver', 'file'); $this->variables['SESSION_DRIVER'] = $this->option('session') ?? $this->choice( 'Session Driver', self::SESSION_DRIVERS, array_key_exists($selected, self::SESSION_DRIVERS) ? $selected : null ); - $selected = config('queue.default', 'redis'); + $selected = config('queue.default', 'sync'); $this->variables['QUEUE_CONNECTION'] = $this->option('queue') ?? $this->choice( 'Queue Driver', self::QUEUE_DRIVERS, From 8ce84239e1a5b25eb8ea321bdd59b775e50de7bb Mon Sep 17 00:00:00 2001 From: Lance Pioch Date: Tue, 9 Apr 2024 19:24:04 -0400 Subject: [PATCH 19/40] Populate new tags --- app/Models/Egg.php | 1 + .../2024_03_12_154408_remove_nests_table.php | 23 +++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/app/Models/Egg.php b/app/Models/Egg.php index a68d6b63d..3d621f8ac 100644 --- a/app/Models/Egg.php +++ b/app/Models/Egg.php @@ -139,6 +139,7 @@ class Egg extends Model 'features' => 'array', 'docker_images' => 'array', 'file_denylist' => 'array', + 'tags' => 'array', ]; } diff --git a/database/migrations/2024_03_12_154408_remove_nests_table.php b/database/migrations/2024_03_12_154408_remove_nests_table.php index b363de80d..e6f09546a 100644 --- a/database/migrations/2024_03_12_154408_remove_nests_table.php +++ b/database/migrations/2024_03_12_154408_remove_nests_table.php @@ -3,12 +3,30 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Artisan; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; return new class extends Migration { public function up(): void { + Schema::table('eggs', function (Blueprint $table) { + $table->text('tags'); + }); + + DB::table('eggs')->update(['tags' => '[]']); + + $eggsWithNests = DB::table('eggs') + ->select(['eggs.id', 'nests.name']) + ->join('nests', 'nests.id', '=', 'eggs.nest_id') + ->get(); + + foreach ($eggsWithNests as $egg) { + DB::table('eggs') + ->where('id', $egg->id) + ->update(['tags' => "[\"$egg->name\"]"]); + } + Schema::table('eggs', function (Blueprint $table) { $table->dropForeign('service_options_nest_id_foreign'); $table->dropColumn('nest_id'); @@ -42,13 +60,14 @@ return new class extends Migration }); Schema::table('eggs', function (Blueprint $table) { + $table->dropColumn('tags'); $table->mediumInteger('nest_id')->unsigned(); - $table->foreign(['nest_id'], 'service_options_nest_id_foreign'); + // $table->foreign(['nest_id'], 'service_options_nest_id_foreign'); }); Schema::table('servers', function (Blueprint $table) { $table->mediumInteger('nest_id')->unsigned(); - $table->foreign(['nest_id'], 'servers_nest_id_foreign'); + // $table->foreign(['nest_id'], 'servers_nest_id_foreign'); }); if (class_exists('Database\Seeders\NestSeeder')) { From f6eede37aac52e27bd2c8daf6cc5ba715e04c6ce Mon Sep 17 00:00:00 2001 From: Lance Pioch Date: Tue, 9 Apr 2024 20:08:55 -0400 Subject: [PATCH 20/40] Populate tags for nodes --- .../2024_03_12_154408_remove_nests_table.php | 6 +++-- ...24_03_14_055537_remove_locations_table.php | 25 ++++++++++++++----- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/database/migrations/2024_03_12_154408_remove_nests_table.php b/database/migrations/2024_03_12_154408_remove_nests_table.php index e6f09546a..1805bb6f0 100644 --- a/database/migrations/2024_03_12_154408_remove_nests_table.php +++ b/database/migrations/2024_03_12_154408_remove_nests_table.php @@ -27,6 +27,7 @@ return new class extends Migration ->update(['tags' => "[\"$egg->name\"]"]); } + Schema::table('eggs', function (Blueprint $table) { $table->dropForeign('service_options_nest_id_foreign'); $table->dropColumn('nest_id'); @@ -44,6 +45,7 @@ return new class extends Migration }); } + // Not really reversible, but... public function down(): void { Schema::table('api_keys', function (Blueprint $table) { @@ -62,12 +64,12 @@ return new class extends Migration Schema::table('eggs', function (Blueprint $table) { $table->dropColumn('tags'); $table->mediumInteger('nest_id')->unsigned(); - // $table->foreign(['nest_id'], 'service_options_nest_id_foreign'); + $table->foreign(['nest_id'], 'service_options_nest_id_foreign'); }); Schema::table('servers', function (Blueprint $table) { $table->mediumInteger('nest_id')->unsigned(); - // $table->foreign(['nest_id'], 'servers_nest_id_foreign'); + $table->foreign(['nest_id'], 'servers_nest_id_foreign'); }); if (class_exists('Database\Seeders\NestSeeder')) { diff --git a/database/migrations/2024_03_14_055537_remove_locations_table.php b/database/migrations/2024_03_14_055537_remove_locations_table.php index bf41cd464..7c72d7617 100644 --- a/database/migrations/2024_03_14_055537_remove_locations_table.php +++ b/database/migrations/2024_03_14_055537_remove_locations_table.php @@ -2,15 +2,30 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; return new class extends Migration { - /** - * Run the migrations. - */ public function up(): void { + Schema::table('nodes', function (Blueprint $table) { + $table->text('tags'); + }); + + DB::table('nodes')->update(['tags' => '[]']); + + $nodesWithLocations = DB::table('nodes') + ->select(['nodes.id', 'locations.short']) + ->join('locations', 'locations.id', '=', 'nodes.location_id') + ->get(); + + foreach ($nodesWithLocations as $node) { + DB::table('nodes') + ->where('id', $node->id) + ->update(['tags' => "[\"$node->short\"]"]); + } + Schema::table('nodes', function (Blueprint $table) { $table->dropForeign('nodes_location_id_foreign'); $table->dropColumn('location_id'); @@ -23,9 +38,7 @@ return new class extends Migration }); } - /** - * Reverse the migrations. - */ + // Not really reversible, but... public function down(): void { Schema::create('locations', function (Blueprint $table) { From f3085afcbc2e1204755e0802bdf4a7bcc5c3961a Mon Sep 17 00:00:00 2001 From: Lance Pioch Date: Wed, 10 Apr 2024 17:10:51 -0400 Subject: [PATCH 21/40] Styling --- database/migrations/2024_03_12_154408_remove_nests_table.php | 1 - 1 file changed, 1 deletion(-) diff --git a/database/migrations/2024_03_12_154408_remove_nests_table.php b/database/migrations/2024_03_12_154408_remove_nests_table.php index 1805bb6f0..2d665d3e3 100644 --- a/database/migrations/2024_03_12_154408_remove_nests_table.php +++ b/database/migrations/2024_03_12_154408_remove_nests_table.php @@ -27,7 +27,6 @@ return new class extends Migration ->update(['tags' => "[\"$egg->name\"]"]); } - Schema::table('eggs', function (Blueprint $table) { $table->dropForeign('service_options_nest_id_foreign'); $table->dropColumn('nest_id'); From 3e90484125cca6e06bdf15e9f438b539cd1b997a Mon Sep 17 00:00:00 2001 From: Huguitis Date: Wed, 10 Apr 2024 23:26:23 +0200 Subject: [PATCH 22/40] passwords.php correction. --- lang/es/passwords.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/es/passwords.php b/lang/es/passwords.php index 293dbaab2..1f0855205 100644 --- a/lang/es/passwords.php +++ b/lang/es/passwords.php @@ -15,5 +15,5 @@ return [ 'reset' => '¡Tu contraseña ha sido restablecida!', 'sent' => '¡Hemos enviado por correo electrónico el enlace para restablecer tu contraseña!', 'token' => 'Este token de restablecimiento de contraseña no es válido.', - 'user' => "No podemos encontrar un usuario con esa dirección de correo electrónico.", + 'user' => 'No podemos encontrar un usuario con esa dirección de correo electrónico.', ]; From 2d93c900607fce7c10d04f610d410cc33b8b8d22 Mon Sep 17 00:00:00 2001 From: Huguitis Date: Wed, 10 Apr 2024 23:27:36 +0200 Subject: [PATCH 23/40] messages.php correction. --- lang/es/command/messages.php | 100 +++++++++++++++++------------------ 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/lang/es/command/messages.php b/lang/es/command/messages.php index 168d05b26..1723749c2 100644 --- a/lang/es/command/messages.php +++ b/lang/es/command/messages.php @@ -1,59 +1,59 @@ [ - 'search_users' => 'Introduce un nombre de usuario, ID de usuario o dirección de correo electrónico', - 'select_search_user' => 'ID del usuario a eliminar (Introduce \'0\' para volver a buscar)', - 'deleted' => 'Usuario eliminado correctamente del Panel.', - 'confirm_delete' => '¿Estás seguro de que quieres eliminar este usuario del Panel?', - 'no_users_found' => 'No se encontraron usuarios para el término de búsqueda proporcionado.', - 'multiple_found' => 'Se encontraron varias cuentas para el usuario proporcionado, no se puede eliminar un usuario debido a la bandera --no-interaction.', - 'ask_admin' => '¿Es este usuario un administrador?', - 'ask_email' => 'Dirección de correo electrónico', - 'ask_username' => 'Nombre de usuario', - 'ask_name_first' => 'Nombre', - 'ask_name_last' => 'Apellido', - 'ask_password' => 'Contraseña', - 'ask_password_tip' => 'Si deseas crear una cuenta con una contraseña aleatoria enviada por correo electrónico al usuario, vuelve a ejecutar este comando (CTRL+C) y pasa la bandera `--no-password`.', - 'ask_password_help' => 'Las contraseñas deben tener al menos 8 caracteres de longitud y contener al menos una letra mayúscula y un número.', - '2fa_help_text' => [ - 'Este comando deshabilitará la autenticación de dos factores para la cuenta de un usuario si está habilitada. Esto solo debe usarse como un comando de recuperación de cuenta si el usuario está bloqueado fuera de su cuenta.', - 'Si esto no es lo que querías hacer, presiona CTRL+C para salir de este proceso.', + 'user' => [ + 'search_users' => 'Introduce un nombre de usuario, ID de usuario o dirección de correo electrónico', + 'select_search_user' => 'ID del usuario a eliminar (Introduce \'0\' para volver a buscar)', + 'deleted' => 'Usuario eliminado correctamente del Panel.', + 'confirm_delete' => '¿Estás seguro de que quieres eliminar este usuario del Panel?', + 'no_users_found' => 'No se encontraron usuarios para el término de búsqueda proporcionado.', + 'multiple_found' => 'Se encontraron varias cuentas para el usuario proporcionado, no se puede eliminar un usuario debido a la bandera --no-interaction.', + 'ask_admin' => '¿Es este usuario un administrador?', + 'ask_email' => 'Dirección de correo electrónico', + 'ask_username' => 'Nombre de usuario', + 'ask_name_first' => 'Nombre', + 'ask_name_last' => 'Apellido', + 'ask_password' => 'Contraseña', + 'ask_password_tip' => 'Si deseas crear una cuenta con una contraseña aleatoria enviada por correo electrónico al usuario, vuelve a ejecutar este comando (CTRL+C) y pasa la bandera `--no-password`.', + 'ask_password_help' => 'Las contraseñas deben tener al menos 8 caracteres de longitud y contener al menos una letra mayúscula y un número.', + '2fa_help_text' => [ + 'Este comando deshabilitará la autenticación de dos factores para la cuenta de un usuario si está habilitada. Esto solo debe usarse como un comando de recuperación de cuenta si el usuario está bloqueado fuera de su cuenta.', + 'Si esto no es lo que querías hacer, presiona CTRL+C para salir de este proceso.', + ], + '2fa_disabled' => 'La autenticación de dos factores ha sido desactivada para :email.', ], - '2fa_disabled' => 'La autenticación de dos factores ha sido desactivada para :email.', -], -'schedule' => [ - 'output_line' => 'Enviando trabajo para la primera tarea en `:schedule` (:hash).', -], -'maintenance' => [ - 'deleting_service_backup' => 'Eliminando archivo de copia de seguridad del servicio :file.', -], -'server' => [ - 'rebuild_failed' => 'La solicitud de reconstrucción para ":name" (#:id) en el nodo ":node" falló con el error: :message', - 'reinstall' => [ - 'failed' => 'La solicitud de reinstalación para ":name" (#:id) en el nodo ":node" falló con el error: :message', - 'confirm' => 'Estás a punto de reinstalar contra un grupo de servidores. ¿Deseas continuar?', + 'schedule' => [ + 'output_line' => 'Enviando trabajo para la primera tarea en `:schedule` (:hash).', ], - 'power' => [ - 'confirm' => 'Estás a punto de realizar una :action contra :count servidores. ¿Deseas continuar?', - 'action_failed' => 'La acción de energía para ":name" (#:id) en el nodo ":node" falló con el error: :message', + 'maintenance' => [ + 'deleting_service_backup' => 'Eliminando archivo de copia de seguridad del servicio :file.', ], -], -'environment' => [ - 'mail' => [ - 'ask_smtp_host' => 'Host SMTP (por ejemplo, smtp.gmail.com)', - 'ask_smtp_port' => 'Puerto SMTP', - 'ask_smtp_username' => 'Nombre de usuario SMTP', - 'ask_smtp_password' => 'Contraseña SMTP', - 'ask_mailgun_domain' => 'Dominio de Mailgun', - 'ask_mailgun_endpoint' => 'Extremo de Mailgun', - 'ask_mailgun_secret' => 'Secreto de Mailgun', - 'ask_mandrill_secret' => 'Secreto de Mandrill', - 'ask_postmark_username' => 'Clave API de Postmark', - 'ask_driver' => '¿Qué controlador debe usarse para enviar correos electrónicos?', - 'ask_mail_from' => 'Dirección de correo electrónico desde la cual deben originarse los correos electrónicos', - 'ask_mail_name' => 'Nombre que debe aparecer en los correos electrónicos', - 'ask_encryption' => 'Método de cifrado a utilizar', + 'server' => [ + 'rebuild_failed' => 'La solicitud de reconstrucción para ":name" (#:id) en el nodo ":node" falló con el error: :message', + 'reinstall' => [ + 'failed' => 'La solicitud de reinstalación para ":name" (#:id) en el nodo ":node" falló con el error: :message', + 'confirm' => 'Estás a punto de reinstalar contra un grupo de servidores. ¿Deseas continuar?', + ], + 'power' => [ + 'confirm' => 'Estás a punto de realizar una :action contra :count servidores. ¿Deseas continuar?', + 'action_failed' => 'La acción de energía para ":name" (#:id) en el nodo ":node" falló con el error: :message', + ], + ], + 'environment' => [ + 'mail' => [ + 'ask_smtp_host' => 'Host SMTP (por ejemplo, smtp.gmail.com)', + 'ask_smtp_port' => 'Puerto SMTP', + 'ask_smtp_username' => 'Nombre de usuario SMTP', + 'ask_smtp_password' => 'Contraseña SMTP', + 'ask_mailgun_domain' => 'Dominio de Mailgun', + 'ask_mailgun_endpoint' => 'Extremo de Mailgun', + 'ask_mailgun_secret' => 'Secreto de Mailgun', + 'ask_mandrill_secret' => 'Secreto de Mandrill', + 'ask_postmark_username' => 'Clave API de Postmark', + 'ask_driver' => '¿Qué controlador debe usarse para enviar correos electrónicos?', + 'ask_mail_from' => 'Dirección de correo electrónico desde la cual deben originarse los correos electrónicos', + 'ask_mail_name' => 'Nombre que debe aparecer en los correos electrónicos', + 'ask_encryption' => 'Método de cifrado a utilizar', ], ], ]; From ef1bd0098b72d61cd21547689a8ffb01e6b0b39d Mon Sep 17 00:00:00 2001 From: Lance Pioch Date: Thu, 11 Apr 2024 20:18:57 -0400 Subject: [PATCH 24/40] Remove hard requirement on posix --- app/Console/Commands/UpgradeCommand.php | 4 ++-- composer.json | 1 - composer.lock | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/app/Console/Commands/UpgradeCommand.php b/app/Console/Commands/UpgradeCommand.php index 45c127767..e04d1a50c 100644 --- a/app/Console/Commands/UpgradeCommand.php +++ b/app/Console/Commands/UpgradeCommand.php @@ -51,7 +51,7 @@ class UpgradeCommand extends Command } if (is_null($this->option('user'))) { - $userDetails = posix_getpwuid(fileowner('public')); + $userDetails = function_exists('posix_getpwuid') ? posix_getpwuid(fileowner('public')) : []; $user = $userDetails['name'] ?? 'www-data'; if (!$this->confirm("Your webserver user has been detected as [{$user}]: is this correct?", true)) { @@ -67,7 +67,7 @@ class UpgradeCommand extends Command } if (is_null($this->option('group'))) { - $groupDetails = posix_getgrgid(filegroup('public')); + $groupDetails = function_exists('posix_getgrgid') ? posix_getgrgid(filegroup('public')) : []; $group = $groupDetails['name'] ?? 'www-data'; if (!$this->confirm("Your webserver group has been detected as [{$group}]: is this correct?", true)) { diff --git a/composer.json b/composer.json index 829ec4d72..612d70119 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,6 @@ "ext-mbstring": "*", "ext-pdo": "*", "ext-pdo_mysql": "*", - "ext-posix": "*", "ext-zip": "*", "aws/aws-sdk-php": "~3.288.1", "doctrine/dbal": "~3.6.0", diff --git a/composer.lock b/composer.lock index 30fdecfd0..72bdbf5ff 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d7166d309ca3cb996fe990be81644539", + "content-hash": "413a3ca00228de8de6f6d74ab817b5d6", "packages": [ { "name": "aws/aws-crt-php", @@ -11037,7 +11037,6 @@ "ext-mbstring": "*", "ext-pdo": "*", "ext-pdo_mysql": "*", - "ext-posix": "*", "ext-zip": "*" }, "platform-dev": [], From 01f63f7122ee0c89b537c919506cef442e00e74c Mon Sep 17 00:00:00 2001 From: Lance Pioch Date: Thu, 11 Apr 2024 20:34:57 -0400 Subject: [PATCH 25/40] =?UTF-8?q?Don=E2=80=99t=20bother=20running=20this?= =?UTF-8?q?=20locally,=20it=E2=80=99s=20not=20meant=20to?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Middleware/VerifyReCaptcha.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/Http/Middleware/VerifyReCaptcha.php b/app/Http/Middleware/VerifyReCaptcha.php index 762a9646d..bfe09ce98 100644 --- a/app/Http/Middleware/VerifyReCaptcha.php +++ b/app/Http/Middleware/VerifyReCaptcha.php @@ -19,6 +19,10 @@ class VerifyReCaptcha return $next($request); } + if (app()->isLocal()) { + return $next($request); + } + if ($request->filled('g-recaptcha-response')) { $client = new Client(); $res = $client->post(config('recaptcha.domain'), [ From 7c575205d3a7f0b9767ac982f5fa57fb471f2cca Mon Sep 17 00:00:00 2001 From: Lance Pioch Date: Thu, 11 Apr 2024 20:59:35 -0400 Subject: [PATCH 26/40] logo and favicon changes # Conflicts: # resources/scripts/components/auth/LoginFormContainer.tsx # resources/scripts/components/elements/PageContentBlock.tsx # resources/views/layouts/admin.blade.php --- public/pelican.ico | Bin 0 -> 267326 bytes public/pelican.svg | 181 ++++++++++++++++++ .../components/auth/LoginFormContainer.tsx | 8 +- .../components/elements/PageContentBlock.tsx | 2 +- resources/views/layouts/admin.blade.php | 8 +- resources/views/templates/wrapper.blade.php | 7 +- 6 files changed, 189 insertions(+), 17 deletions(-) create mode 100644 public/pelican.ico create mode 100644 public/pelican.svg diff --git a/public/pelican.ico b/public/pelican.ico new file mode 100644 index 0000000000000000000000000000000000000000..dbf198f25864b1c03c78676aca061fd0de03c056 GIT binary patch literal 267326 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/scripts/components/auth/LoginFormContainer.tsx b/resources/scripts/components/auth/LoginFormContainer.tsx index 74530c00a..23fa6ad9a 100644 --- a/resources/scripts/components/auth/LoginFormContainer.tsx +++ b/resources/scripts/components/auth/LoginFormContainer.tsx @@ -34,12 +34,14 @@ export default forwardRef(({ title, ...props }, ref) =>
-
- +
+
{props.children}
-

© 2015 - {new Date().getFullYear()} 

+

+ Pelican © 2024 - {new Date().getFullYear()}  +

)); diff --git a/resources/scripts/components/elements/PageContentBlock.tsx b/resources/scripts/components/elements/PageContentBlock.tsx index b070b071c..1f62eedb5 100644 --- a/resources/scripts/components/elements/PageContentBlock.tsx +++ b/resources/scripts/components/elements/PageContentBlock.tsx @@ -34,7 +34,7 @@ const PageContentBlock: React.FC = ({ title, showFlashKey > Panel -  © 2015 - {new Date().getFullYear()} +  Pelican© 2024 - {new Date().getFullYear()}

diff --git a/resources/views/layouts/admin.blade.php b/resources/views/layouts/admin.blade.php index 3f82dea47..629547d4d 100644 --- a/resources/views/layouts/admin.blade.php +++ b/resources/views/layouts/admin.blade.php @@ -7,13 +7,7 @@ - - - - - - - + @include('layouts.scripts') diff --git a/resources/views/templates/wrapper.blade.php b/resources/views/templates/wrapper.blade.php index 4c2705517..8e52dc80c 100644 --- a/resources/views/templates/wrapper.blade.php +++ b/resources/views/templates/wrapper.blade.php @@ -9,12 +9,7 @@ - - - - - - + @show From b39e1c6f78b59360e71e1b973e1bf294b544b6c6 Mon Sep 17 00:00:00 2001 From: iamkubi Date: Sat, 13 Apr 2024 14:31:16 -0700 Subject: [PATCH 27/40] Add CLA and workflow for CLA bot --- .github/workflows/cla.yaml | 27 +++++++++ contributor_license_agreement.md | 96 ++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 .github/workflows/cla.yaml create mode 100644 contributor_license_agreement.md diff --git a/.github/workflows/cla.yaml b/.github/workflows/cla.yaml new file mode 100644 index 000000000..27650fd54 --- /dev/null +++ b/.github/workflows/cla.yaml @@ -0,0 +1,27 @@ +name: "CLA Assistant" +on: + issue_comment: + types: [created] + pull_request_target: + types: [opened,closed,synchronize] + +permissions: + actions: write + contents: write + pull-requests: write + statuses: write + +jobs: + CLAAssistant: + runs-on: ubuntu-latest + steps: + - name: "CLA Assistant" + if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target' + uses: contributor-assistant/github-action@v2.3.0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + path-to-signatures: '.cla-signatures/version1/cla.json' + path-to-document: 'https://github.com/pelican-dev/panel/blob/3.x/contributor_license_agreement.md' + branch: '3.x' + allowlist: dependabot[bot] diff --git a/contributor_license_agreement.md b/contributor_license_agreement.md new file mode 100644 index 000000000..8594ea679 --- /dev/null +++ b/contributor_license_agreement.md @@ -0,0 +1,96 @@ +Thank you for your interest in Pelican ("Pelican Developers"). To clarify the intellectual property license +granted with Contributions from any person or entity, the Pelican Developers +must have on file a signed Contributor License Agreement ("CLA") +from each Contributor, indicating agreement with the license +terms below. This agreement is for your protection as a Contributor +as well as the protection of the Pelican Developers and its users. It does not +change your rights to use your own Contributions for any other purpose. + +You accept and agree to the following terms and conditions for Your +Contributions (present and future) that you submit to the Pelican Developers. In +return, the Pelican Developers shall not use Your Contributions in a way that +is contrary to the public benefit or inconsistent with its nonprofit +status and bylaws in effect at the time of the Contribution. Except +for the license granted herein to the Pelican Developers and recipients of +software distributed by the Pelican Developers, You reserve all right, title, +and interest in and to Your Contributions. +1. Definitions. + "You" (or "Your") shall mean the copyright owner or legal entity + authorized by the copyright owner that is making this Agreement + with the Pelican Developers. For legal entities, the entity making a + Contribution and all other entities that control, are controlled + by, or are under common control with that entity are considered to + be a single Contributor. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + "Contribution" shall mean any original work of authorship, + including any modifications or additions to an existing work, that + is intentionally submitted by You to the Pelican Developers for inclusion + in, or documentation of, any of the products owned or managed by + the Pelican Developers (the "Work"). For the purposes of this definition, + "submitted" means any form of electronic, verbal, or written + communication sent to the Pelican Developers or its representatives, + including but not limited to communication on electronic mailing + lists, source code control systems, and issue tracking systems that + are managed by, or on behalf of, the Pelican Developers for the purpose of + discussing and improving the Work, but excluding communication that + is conspicuously marked or otherwise designated in writing by You + as "Not a Contribution." +2. Grant of Copyright License. Subject to the terms and conditions of + this Agreement, You hereby grant to the Pelican Developers and to + recipients of software distributed by the Pelican Developers a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare derivative works of, + publicly display, publicly perform, sublicense, and distribute Your + Contributions and such derivative works. +3. Grant of Patent License. Subject to the terms and conditions of + this Agreement, You hereby grant to the Pelican Developers and to + recipients of software distributed by the Pelican Developers a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have + made, use, offer to sell, sell, import, and otherwise transfer the + Work, where such license applies only to those patent claims + licensable by You that are necessarily infringed by Your + Contribution(s) alone or by combination of Your Contribution(s) + with the Work to which such Contribution(s) was submitted. If any + entity institutes patent litigation against You or any other entity + (including a cross-claim or counterclaim in a lawsuit) alleging + that your Contribution, or the Work to which you have contributed, + constitutes direct or contributory patent infringement, then any + patent licenses granted to that entity under this Agreement for + that Contribution or Work shall terminate as of the date such + litigation is filed. +4. You represent that you are legally entitled to grant the above + license. If your employer(s) has rights to intellectual property + that you create that includes your Contributions, you represent + that you have received permission to make Contributions on behalf + of that employer, that your employer has waived such rights for + your Contributions to the Pelican Developers, or that your employer has + executed a separate Corporate CLA with the Pelican Developers. +5. You represent that each of Your Contributions is Your original + creation (see section 7 for submissions on behalf of others). You + represent that Your Contribution submissions include complete + details of any third-party license or other restriction (including, + but not limited to, related patents and trademarks) of which you + are personally aware and which are associated with any part of Your + Contributions. +6. You are not expected to provide support for Your Contributions, + except to the extent You desire to provide support. You may provide + support for free, for a fee, or not at all. Unless required by + applicable law or agreed to in writing, You provide Your + Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + OF ANY KIND, either express or implied, including, without + limitation, any warranties or conditions of TITLE, NON- + INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. +7. Should You wish to submit work that is not Your original creation, + You may submit it to the Pelican Developers separately from any + Contribution, identifying the complete details of its source and of + any license or other restriction (including, but not limited to, + related patents, trademarks, and license agreements) of which you + are personally aware, and conspicuously marking the work as + "Submitted on behalf of a third-party: [named here]". +8. You agree to notify the Pelican Developers of any facts or circumstances of + which you become aware that would make these representations + inaccurate in any respect. From 3e940e8c487b6829d43f9e83143b4b289702f809 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 13 Apr 2024 21:39:29 +0000 Subject: [PATCH 28/40] Creating file for storing CLA Signatures --- .cla-signatures/version1/cla.json | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .cla-signatures/version1/cla.json diff --git a/.cla-signatures/version1/cla.json b/.cla-signatures/version1/cla.json new file mode 100644 index 000000000..18d5487f3 --- /dev/null +++ b/.cla-signatures/version1/cla.json @@ -0,0 +1,3 @@ +{ + "signedContributors": [] +} \ No newline at end of file From 3b0c5540a7b36bf9a18245dd53f7c5e9be0d599f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 13 Apr 2024 21:40:08 +0000 Subject: [PATCH 29/40] @iamkubi has signed the CLA in pelican-dev/panel#64 --- .cla-signatures/version1/cla.json | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.cla-signatures/version1/cla.json b/.cla-signatures/version1/cla.json index 18d5487f3..20b065ad5 100644 --- a/.cla-signatures/version1/cla.json +++ b/.cla-signatures/version1/cla.json @@ -1,3 +1,12 @@ { - "signedContributors": [] + "signedContributors": [ + { + "name": "iamkubi", + "id": 6176191, + "comment_id": 2053767631, + "created_at": "2024-04-13T21:39:53Z", + "repoId": 774258963, + "pullRequestNo": 64 + } + ] } \ No newline at end of file From 67fa753e7bcbc32e81ad512e98281a3182b5cbea Mon Sep 17 00:00:00 2001 From: iamkubi Date: Sat, 13 Apr 2024 16:30:02 -0700 Subject: [PATCH 30/40] Update license --- license | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/license b/license index fe6b9036b..301cbf999 100644 --- a/license +++ b/license @@ -1,3 +1,7 @@ +Pelican Panel is offered under the AGPL-3 license to the open source community. +Pelican Panel is alternatively available under a commercial license. +Contact team@pelican.dev for information about commercial licensing. + GNU AFFERO GENERAL PUBLIC LICENSE Version 3, 19 November 2007 From e96dd13170bebe4eb4f95e32183d5df46eee6850 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 14 Apr 2024 01:59:18 +0000 Subject: [PATCH 31/40] @notAreYouScared has signed the CLA in pelican-dev/panel#66 --- .cla-signatures/version1/cla.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.cla-signatures/version1/cla.json b/.cla-signatures/version1/cla.json index 20b065ad5..99412fcdf 100644 --- a/.cla-signatures/version1/cla.json +++ b/.cla-signatures/version1/cla.json @@ -7,6 +7,14 @@ "created_at": "2024-04-13T21:39:53Z", "repoId": 774258963, "pullRequestNo": 64 + }, + { + "name": "notAreYouScared", + "id": 1757840, + "comment_id": 2053849162, + "created_at": "2024-04-14T01:59:04Z", + "repoId": 774258963, + "pullRequestNo": 66 } ] } \ No newline at end of file From 867777f2e4f5cbe93f67ccf99d525e38c9b87f4d Mon Sep 17 00:00:00 2001 From: Lance Pioch Date: Sun, 14 Apr 2024 13:18:59 -0400 Subject: [PATCH 32/40] Update Crowdin configuration file --- crowdin.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 crowdin.yml diff --git a/crowdin.yml b/crowdin.yml new file mode 100644 index 000000000..bbcc6cbbb --- /dev/null +++ b/crowdin.yml @@ -0,0 +1,3 @@ +files: + - source: /lang/en/*.php + translation: /lang/%two_letters_code%/%original_file_name% From 0195e36ccf4fe89cf39a704e9f500cc4b656dc59 Mon Sep 17 00:00:00 2001 From: Lance Pioch Date: Sun, 14 Apr 2024 13:54:15 -0400 Subject: [PATCH 33/40] Update Crowdin configuration file --- crowdin.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crowdin.yml b/crowdin.yml index bbcc6cbbb..6f49cab9d 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -1,3 +1,11 @@ files: - source: /lang/en/*.php translation: /lang/%two_letters_code%/%original_file_name% + - source: /lang/en/admin + translation: /lang/%two_letters_code%/admin/%original_file_name% + - source: /lang/en/command + translation: /lang/%two_letters_code%/command/%original_file_name% + - source: /lang/en/dashboard + translation: /lang/%two_letters_code%/dashboard/%original_file_name% + - source: /lang/en/server + translation: /lang/%two_letters_code%/server/%original_file_name% From 2743698e2c6c1dc9fcf0e4cfdad51f20525b96ee Mon Sep 17 00:00:00 2001 From: Lance Pioch Date: Sun, 14 Apr 2024 21:23:41 -0400 Subject: [PATCH 34/40] Fix these again --- .github/workflows/build.yaml | 3 --- .github/workflows/ci.yaml | 2 +- .github/workflows/lint.yaml | 3 --- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 4aed1d674..be1b59369 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,9 +1,6 @@ name: Build on: - push: - branches: - - '**' pull_request: branches: - '**' diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 95458fcd2..81f80c4e9 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -1,7 +1,7 @@ name: Tests on: - push: + pull_request: branches: - '**' diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index ab4515283..3dd538aad 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -1,9 +1,6 @@ name: Lint on: - push: - branches: - - '**' pull_request: branches: - '**' From 5c450900fd3c64062a2cdcdaa2e3233738a4c8bd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 13:42:46 +0000 Subject: [PATCH 35/40] @MikkelHebel has signed the CLA in pelican-dev/panel#86 --- .cla-signatures/version1/cla.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.cla-signatures/version1/cla.json b/.cla-signatures/version1/cla.json index 99412fcdf..15bc4aa70 100644 --- a/.cla-signatures/version1/cla.json +++ b/.cla-signatures/version1/cla.json @@ -15,6 +15,14 @@ "created_at": "2024-04-14T01:59:04Z", "repoId": 774258963, "pullRequestNo": 66 + }, + { + "name": "MikkelHebel", + "id": 88710599, + "comment_id": 2056893499, + "created_at": "2024-04-15T13:42:34Z", + "repoId": 774258963, + "pullRequestNo": 86 } ] } \ No newline at end of file From f6d068be2c8a63e3f418fc8af4f937077d386393 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 17 Apr 2024 14:11:17 +0000 Subject: [PATCH 36/40] @Poseidon281 has signed the CLA in pelican-dev/panel#94 --- .cla-signatures/version1/cla.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.cla-signatures/version1/cla.json b/.cla-signatures/version1/cla.json index 15bc4aa70..a736f6323 100644 --- a/.cla-signatures/version1/cla.json +++ b/.cla-signatures/version1/cla.json @@ -23,6 +23,14 @@ "created_at": "2024-04-15T13:42:34Z", "repoId": 774258963, "pullRequestNo": 86 + }, + { + "name": "Poseidon281", + "id": 62171904, + "comment_id": 2061357850, + "created_at": "2024-04-17T14:10:39Z", + "repoId": 774258963, + "pullRequestNo": 94 } ] } \ No newline at end of file From dd913008c196a9c6e24262fcc6cf5dfd5879e4c7 Mon Sep 17 00:00:00 2001 From: iamkubi Date: Wed, 17 Apr 2024 20:15:07 -0700 Subject: [PATCH 37/40] Update CLA workflow Store signatures in a separate repo --- .github/workflows/cla.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/cla.yaml b/.github/workflows/cla.yaml index 27650fd54..7662ac338 100644 --- a/.github/workflows/cla.yaml +++ b/.github/workflows/cla.yaml @@ -25,3 +25,5 @@ jobs: path-to-document: 'https://github.com/pelican-dev/panel/blob/3.x/contributor_license_agreement.md' branch: '3.x' allowlist: dependabot[bot] + remote-organization-name: pelican-dev + remote-repository-name: cla-signatures From 8801d1db59349dbd160060295e896312c7466e0e Mon Sep 17 00:00:00 2001 From: iamkubi Date: Wed, 17 Apr 2024 20:19:47 -0700 Subject: [PATCH 38/40] Update cla.yaml --- .github/workflows/cla.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cla.yaml b/.github/workflows/cla.yaml index 7662ac338..e073231fd 100644 --- a/.github/workflows/cla.yaml +++ b/.github/workflows/cla.yaml @@ -21,9 +21,9 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - path-to-signatures: '.cla-signatures/version1/cla.json' + path-to-signatures: 'version1/cla.json' path-to-document: 'https://github.com/pelican-dev/panel/blob/3.x/contributor_license_agreement.md' - branch: '3.x' + branch: 'main' allowlist: dependabot[bot] remote-organization-name: pelican-dev remote-repository-name: cla-signatures From 56dbac6f81932f747f61ff3eb5d99459b10830c7 Mon Sep 17 00:00:00 2001 From: iamkubi Date: Wed, 17 Apr 2024 22:49:15 -0700 Subject: [PATCH 39/40] Fix CLA workflow missing access token --- .github/workflows/cla.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/cla.yaml b/.github/workflows/cla.yaml index e073231fd..4efdecca4 100644 --- a/.github/workflows/cla.yaml +++ b/.github/workflows/cla.yaml @@ -20,6 +20,7 @@ jobs: uses: contributor-assistant/github-action@v2.3.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }} with: path-to-signatures: 'version1/cla.json' path-to-document: 'https://github.com/pelican-dev/panel/blob/3.x/contributor_license_agreement.md' From 03574ce4b3432e023ae3447ab2bf4320221cc780 Mon Sep 17 00:00:00 2001 From: iamkubi Date: Wed, 17 Apr 2024 22:57:14 -0700 Subject: [PATCH 40/40] Delete migrated CLA signatures --- .cla-signatures/version1/cla.json | 36 ------------------------------- 1 file changed, 36 deletions(-) delete mode 100644 .cla-signatures/version1/cla.json diff --git a/.cla-signatures/version1/cla.json b/.cla-signatures/version1/cla.json deleted file mode 100644 index a736f6323..000000000 --- a/.cla-signatures/version1/cla.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "signedContributors": [ - { - "name": "iamkubi", - "id": 6176191, - "comment_id": 2053767631, - "created_at": "2024-04-13T21:39:53Z", - "repoId": 774258963, - "pullRequestNo": 64 - }, - { - "name": "notAreYouScared", - "id": 1757840, - "comment_id": 2053849162, - "created_at": "2024-04-14T01:59:04Z", - "repoId": 774258963, - "pullRequestNo": 66 - }, - { - "name": "MikkelHebel", - "id": 88710599, - "comment_id": 2056893499, - "created_at": "2024-04-15T13:42:34Z", - "repoId": 774258963, - "pullRequestNo": 86 - }, - { - "name": "Poseidon281", - "id": 62171904, - "comment_id": 2061357850, - "created_at": "2024-04-17T14:10:39Z", - "repoId": 774258963, - "pullRequestNo": 94 - } - ] -} \ No newline at end of file