LCOV - code coverage report
Current view: top level - pkg/users - account-logs-panel.jsx Coverage Total Hit
Test: cockpit Lines: 98.0 % 51 50
Test Date: 2026-07-03 07:31:16

            Line data    Source code
       1              : /*
       2              :  * Copyright (C) 2021 Red Hat, Inc.
       3              :  * SPDX-License-Identifier: LGPL-2.1-or-later
       4              :  */
       5              : 
       6           19 : import cockpit from 'cockpit';
       7           19 : import React, { useState } from 'react';
       8              : 
       9              : import { Card, CardBody, CardTitle } from "@patternfly/react-core/dist/esm/components/Card/index.js";
      10              : import { ListingTable } from 'cockpit-components-table.jsx';
      11              : 
      12              : import * as timeformat from "timeformat";
      13              : import { useInit } from "hooks";
      14              : 
      15           19 : const _ = cockpit.gettext;
      16              : 
      17           11 : export function AccountLogs({ name }) {
      18           11 :     const [logins, setLogins] = useState([]);
      19           11 :     useInit(() => {
      20           11 :         cockpit.spawn(["last", "--time-format", "iso", "-n25", "--fullnames", name], { environ: ["LC_ALL=C"] })
      21           11 :                 .then(data => {
      22           11 :                     let logins = [];
      23           11 :                     data.split('\n').forEach(line => {
      24              :                         // Exclude still logged in and non user lines
      25            8 :                         if (!line.includes(name) || line.includes('still')) {
      26           11 :                             return;
      27           11 :                         }
      28              :                         // Exclude tmux/screen lines
      29            2 :                         if (line.includes('tmux') || line.includes('screen')) {
      30            2 :                             return;
      31            2 :                         }
      32              : 
      33              :                         // format:
      34              :                         // admin    web console  ::ffff:172.27.0. 2021-09-24T09:02:13+00:00 - 2021-09-24T09:04:20+00:00  (00:02)
      35            7 :                         const lines = line.split(/ +/);
      36            7 :                         const ended = new Date(lines[lines.length - 2]);
      37            7 :                         const started = new Date(lines[lines.length - 4]);
      38            7 :                         const from = lines[lines.length - 5];
      39            2 :                         if (isNaN(started.getTime()) || isNaN(ended.getTime())) {
      40            2 :                             return;
      41            2 :                         }
      42              : 
      43            7 :                         logins.push({
      44            7 :                             started,
      45            7 :                             ended,
      46            7 :                             from
      47            7 :                         });
      48           11 :                     });
      49              : 
      50              :                     // Only show 15 login lines
      51           11 :                     logins = logins.slice(0, 15);
      52           11 :                     setLogins(logins);
      53           11 :                 })
      54            0 :                 .catch(ex => console.error("Failed to call last:", ex)); // not-covered: OS error
      55           11 :     }, [name]);
      56              : 
      57           11 :     return (
      58           11 :         <Card isPlain id="account-logs">
      59           11 :             <CardTitle component="h2">{_("Login history")}</CardTitle>
      60           11 :             <CardBody className="contains-list">
      61           11 :                 <ListingTable variant="compact" aria-label={ _("Login history list") }
      62           11 :                     columns={ [
      63           11 :                         { title: _("Started") },
      64           11 :                         { title: _("Ended") },
      65           11 :                         { title: _("From") },
      66           11 :                     ] }
      67            6 :                     rows={ logins.map((line, index) => ({
      68            6 :                         props: { key: index },
      69            6 :                         columns: [timeformat.dateTime(line.started), timeformat.dateTime(line.ended), line.from]
      70            6 :                     }))} />
      71           11 :             </CardBody>
      72           11 :         </Card>
      73              :     );
      74           11 : }
        

Generated by: LCOV version 2.0-1