#!/usr/bin/env ruby
# SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
# SPDX-FileCopyrightText: 2018 Harald Sitter <sitter@kde.org>
# frozen_string_literal: true

require 'etc'
require 'fileutils'

# Helper class to edit group memberships.
class Group
  def initialize(name)
    @name = name
  end

  def add(user)
    return if system('adduser', user, @name)

    raise "Failed to add #{user} to #{@name}"
  end

  def remove(user)
    return if system('deluser', user, @name)

    raise "Failed to drop #{user} from #{@name}"
  end
end

# Calamares for a whole while created users with wrong groups.
# To mitigate this we automatically mangle UID 1000 to be in certain groups
# and remove it from certain groups.
class Migrator
  ADD_GROUPS = %w[cdrom dip plugdev].freeze
  REMOVE_GROUPS = %w[lp video network storage audio].freeze

  def initialize
    @root = ENV['ROOT']
  end

  def disable
    FileUtils.mkpath("#{@root}/var/lib/neon/")
    File.write("#{@root}/var/lib/neon/update-calamares-groups", '')
  end

  def installed_by_calamares
    # Calamares doesn't create the version marker, ubiquity does.
    # To be future save we'll also check the contents though.
    version_marker = "#{@root}/var/log/installer/version"
    if File.exist?(version_marker)
      data = File.read(version_marker)
      return data.downcase.include?('calamares')
    end
    true
  end

  def run
    unless installed_by_calamares
      puts 'System not installed by calamares. Nothing to fix.'
      disable
      return
    end

    user = Etc.getpwuid(1000).name
    unless user
      warn 'Could not resolve user 1000 to a name, assuming it does not exist'
      disable
      return
    end

    groups = {}
    Etc.group do |group|
      # NB: this will also step over the user's primary group, but we do not
      # want to mangle that in any case. (e.g. user 'me' with group 'me'
      # will not have `'me'.mem.include('me')==true`)
      next unless group.mem.include?(user)

      groups[group.name] = Group.new(group.name)
    end

    # These are defaults used by ubiquity.
    %w[cdrom dip plugdev].each do |name|
      next unless groups.include?(name)

      groups[name].add(user)
    end

    # These are not.
    %w[lp video network storage audio].each do |name|
      next unless groups.include?(name)

      groups[name].remove(user)
    end

    disable
  end
end

Migrator.new.run if $PROGRAM_NAME == __FILE__
