• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

yast / yast-users / 5453098972

pending completion
5453098972

Pull #383

github

web-flow
Merge 54d62cefa into f91b954c3
Pull Request #383: User creation page got messed when going back after importing user(s) from existing installation

16 of 16 new or added lines in 1 file covered. (100.0%)

3319 of 5513 relevant lines covered (60.2%)

35.75 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

11.31
/src/include/users/widgets.rb
1
# encoding: utf-8
2

3
# ------------------------------------------------------------------------------
4
# Copyright (c) 2006-2012 Novell, Inc. All Rights Reserved.
5
#
6
#
7
# This program is free software; you can redistribute it and/or modify it under
8
# the terms of version 2 of the GNU General Public License as published by the
9
# Free Software Foundation.
10
#
11
# This program is distributed in the hope that it will be useful, but WITHOUT
12
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License along with
16
# this program; if not, contact Novell, Inc.
17
#
18
# To contact Novell about this file by physical or electronic mail, you may find
19
# current contact information at www.novell.com.
20
# ------------------------------------------------------------------------------
21

22
# File:        include/users/widgets.ycp
23
# Package:        Configuration of users and groups
24
# Summary:        Widgets definitions and helper functions
25
# Authors:        Jiri Suchomel <jsuchome@suse.cz>
26
#
27

28
require "shellwords"
1✔
29

30
module Yast
1✔
31
  module UsersWidgetsInclude
1✔
32
    def initialize_users_widgets(include_target)
1✔
33
      Yast.import "UI"
18✔
34

35
      Yast.import "Autologin"
18✔
36
      Yast.import "CWMTab"
18✔
37
      Yast.import "Label"
18✔
38
      Yast.import "Ldap"
18✔
39
      Yast.import "Message"
18✔
40
      Yast.import "Mode"
18✔
41
      Yast.import "Package"
18✔
42
      Yast.import "Popup"
18✔
43
      Yast.import "Progress"
18✔
44
      Yast.import "Report"
18✔
45
      Yast.import "Stage"
18✔
46
      Yast.import "String"
18✔
47
      Yast.import "Summary"
18✔
48
      Yast.import "Users"
18✔
49
      Yast.import "UsersCache"
18✔
50
      Yast.import "UsersLDAP"
18✔
51
      Yast.import "UsersRoutines"
18✔
52
      Yast.import "Wizard"
18✔
53

54
      Yast.include include_target, "users/complex.rb"
18✔
55
      Yast.include include_target, "users/routines.rb"
18✔
56
      Yast.include include_target, "users/ldap_dialogs.rb"
18✔
57

58
      textdomain "users"
18✔
59

60
      # values to MenuItem in Summary dialog
61
      @userset_to_string = {
62
        # the type of user set
63
        "system" => _("&System Users"),
18✔
64
        # the type of user set
65
        "local"  => _("&Local Users"),
66
        # the type of user set
67
        "nis"    => _("&NIS Users"),
68
        # the type of user set
69
        "ldap"   => _("L&DAP Users"),
70
        # the type of user set
71
        "samba"  => _("Sam&ba Users"),
72
        # the type of user set
73
        "custom" => _("&Custom")
74
      }
75

76
      # values to Label (no shortcut sign)
77
      @userset_to_label = {
78
        # the type of user set
79
        "system" => _("System Users"),
18✔
80
        # the type of user set
81
        "local"  => _("Local Users"),
82
        # the type of user set
83
        "nis"    => _("NIS Users"),
84
        # the type of user set
85
        "ldap"   => _("LDAP Users"),
86
        # the type of user set
87
        "samba"  => _("Samba Users"),
88
        # the type of user set
89
        "custom" => _("Custom")
90
      }
91

92
      # values to MenuItem in Summary dialog
93
      @groupset_to_string = {
94
        # the type of group set
95
        "system" => _("&System Groups"),
18✔
96
        # the type of group set
97
        "local"  => _("&Local Groups"),
98
        # the type of group set
99
        "nis"    => _("&NIS Groups"),
100
        # the type of group set
101
        "ldap"   => _("L&DAP Groups"),
102
        # the type of group set
103
        "samba"  => _("Sam&ba Groups"),
104
        # the type of group set
105
        "custom" => _("&Custom")
106
      }
107

108
      @groupset_to_label = {
109
        # the type of group set
110
        "system" => _("System Groups"),
18✔
111
        # the type of group set
112
        "local"  => _("Local Groups"),
113
        # the type of group set
114
        "nis"    => _("NIS Groups"),
115
        # the type of group set
116
        "ldap"   => _("LDAP Groups"),
117
        # the type of group set
118
        "samba"  => _("Samba Groups"),
119
        # the type of group set
120
        "custom" => _("Custom")
121
      }
122

123
      # map with group names allowed for a default group
124
      @all_groupnames = {}
18✔
125

126
      # global values for authentication tab: ---------
127

128
      # list of installed clients
129
      @installed_clients = []
18✔
130

131
      @configurable_clients = ["nis", "sssd", "samba"]
18✔
132

133
      # save if no more Available calls should be done (bug #225484)
134
      @check_available = true
18✔
135

136
      @client_label = {
137
        # richtext label
138
        "nis"      => _("NIS"),
18✔
139
        # richtext label
140
        "sssd"     => _("SSSD"),
141
        # richtext label
142
        "samba"    => _("Samba")
143
      }
144

145
      # auth methods and respective module calls
146
      @auth_methods = {
147
        "nis" => {
18✔
148
          # menubutton label
149
          "label" => _("&NIS"),
150
          "package" => "yast2-nis-client",
151
          "call" => "nis-client"
152
        },
153
        "sssd" => {
154
          # menubutton label
155
          "label" => _("&SSSD"),
156
          "package" => "yast2-auth-client",
157
          "call" => "auth-client"
158
        },
159
        "samba" => {
160
          # menubutton label
161
          "label" => _("&Samba"),
162
          "package" => "yast2-samba-client",
163
          "call" => "samba-client"
164
        },
165
      }
166

167
      @tabs_description = {
168
        "users"          => {
18✔
169
          # tab header
170
          "header"       => _("&Users"),
171
          "contents"     => HBox(
172
            HSpacing(0.5),
173
            VBox("filter_line", "tab_switch_users", "table"),
174
            HSpacing(0.5)
175
          ),
176
          "widget_names" => ["tab_switch_users", "filter_line", "table"]
177
        },
178
        "groups"         => {
179
          # tab header
180
          "header"       => _("&Groups"),
181
          "contents"     => HBox(
182
            HSpacing(0.5),
183
            VBox("filter_line", "tab_switch_groups", "table"),
184
            HSpacing(0.5)
185
          ),
186
          "widget_names" => ["tab_switch_groups", "filter_line", "table"]
187
        },
188
        "defaults"       => {
189
          # tab header
190
          "header"       => _("De&faults for New Users"),
191
          "contents"     => HBox(
192
            HSpacing(2),
193
            VBox(
194
              VStretch(),
195
              VSpacing(0.2),
196
              "defaults_global",
197
              "defaultgroup",
198
              "shell",
199
              HBox("home", VBox(Label(""), "browse_home")),
200
              "umask",
201
              "expire",
202
              "inactive",
203
              VSpacing(0.2),
204
              VStretch()
205
            ),
206
            HSpacing(2)
207
          ),
208
          "widget_names" => [
209
            "defaults_global",
210
            "defaultgroup",
211
            "shell",
212
            "home",
213
            "browse_home",
214
            "umask",
215
            "expire",
216
            "inactive"
217
          ]
218
        },
219
        "authentication" => {
220
          # tab header
221
          "header"       => _("&Authentication Settings"),
222
          "contents"     => HBox(
223
            HSpacing(),
224
            VBox(VSpacing(0.5), "auth_global", VSpacing(0.5)),
225
            HSpacing()
226
          ),
227
          "widget_names" => ["auth_global"]
228
        }
229
      }
230

231

232
      @widgets = {
233
        # widgets for "users" and "groups" tabs ---------------------------------
234
        "tab_switch_users"  => {
18✔
235
          "widget" => :empty,
236
          "init"   => fun_ref(method(:InitTabUsersGroups), "void (string)"),
237
          "help"   => UsersDialogHelp()
238
        },
239
        "tab_switch_groups" => {
240
          "widget" => :empty,
241
          "init"   => fun_ref(method(:InitTabUsersGroups), "void (string)"),
242
          "help"   => GroupsDialogHelp()
243
        },
244
        "filter_line"       => {
245
          "widget"        => :custom,
246
          "custom_widget" => ReplacePoint(
247
            Id(:rpfilter),
248
            HBox(
249
              Left(Label(Id(:current_filter), "")),
250
              Right(
251
                MenuButton(
252
                  Id(:sets),
253
                  Opt(:key_F2, :disabled),
254
                  _("&Set Filter"),
255
                  []
256
                )
257
              )
258
            )
259
          ),
260
          "init"          => fun_ref(method(:InitFilterLine), "void (string)"),
261
          "handle"        => fun_ref(
262
            method(:HandleFilterLine),
263
            "symbol (string, map)"
264
          ),
265
          "handle_events" => [
266
            # these are for user/group types
267
            "local",
268
            "system",
269
            "ldap",
270
            "nis",
271
            "custom",
272
            :customize
273
          ],
274
          "no_help"       => true
275
        },
276
        "table"             => {
277
          "widget"        => :custom,
278
          "custom_widget" => VBox(
279
            ReplacePoint(Id(:rptable), Table(Id("table"), Header(""))),
280
            HBox(
281
              PushButton(Id(:new), Opt(:key_F3), Label.AddButton),
282
              PushButton(Id(:edit), Opt(:key_F4), Label.EditButton),
283
              PushButton(Id(:delete), Opt(:key_F5), Label.DeleteButton),
284
              HStretch(),
285
              ReplacePoint(
286
                Id(:rpexpert),
287
                # Menu Buton label
288
                MenuButton(Id(:expertlist), _("E&xpert Options"), [])
289
              )
290
            ),
291
            VSpacing(0.2)
292
          ),
293
          "init"          => fun_ref(method(:SummaryTableInit), "void (string)"),
294
          "handle"        => fun_ref(
295
            method(:HandleSummaryTable),
296
            "symbol (string, map)"
297
          ),
298
          "handle_events" => [
299
            "table",
300
            :new,
301
            :edit,
302
            :delete,
303
            :next,
304
            :enc,
305
            :autologinconf,
306
            :save,
307
            :ldapfilter,
308
            :ldapconf
309
          ],
310
          "no_help"       => true
311
        },
312
        # widgets for user defaults --------------------------------------------
313
        "defaults_global"   => {
314
          "widget" => :empty,
315
          "init"   => fun_ref(method(:InitDefaults), "void (string)"),
316
          "store"  => fun_ref(method(:StoreDefaults), "void (string, map)"),
317
          "help"   => DefaultsDialogHelp()
318
        },
319
        "defaultgroup"      => {
320
          "widget"  => :combobox,
321
          "opt"     => [:hstretch],
322
          # combobox label
323
          "label"   => _("D&efault Group"),
324
          "no_help" => true
325
        },
326
        "shell"             => {
327
          "widget"            => :combobox,
328
          "opt"               => [:hstretch, :editable],
329
          # combobox label
330
          "label"             => _("Default &Login Shell"),
331
          "no_help"           => true,
332
          "validate_type"     => :function,
333
          "validate_function" => fun_ref(
334
            method(:ValidateShell),
335
            "boolean (string, map)"
336
          )
337
        },
338
        "home"              => {
339
          "widget"            => :textentry,
340
          # text entry
341
          "label"             => _(
342
            "Path Prefix for &Home Directory"
343
          ),
344
          "no_help"           => true,
345
          "validate_type"     => :function,
346
          "validate_function" => fun_ref(
347
            method(:ValidateHomePrefix),
348
            "boolean (string, map)"
349
          )
350
        },
351
        "browse_home"       => {
352
          "widget"  => :push_button,
353
          # push button label
354
          "label"   => _("&Browse..."),
355
          "opt"     => [:key_F6],
356
          "handle"  => fun_ref(
357
            method(:HandleBrowseDirectory),
358
            "symbol (string, map)"
359
          ),
360
          "no_help" => true
361
        },
362
        "expire"            => {
363
          "widget"            => :textentry,
364
          # text entry
365
          "label"             => _("Default E&xpiration Date"),
366
          "no_help"           => true,
367
          "validate_type"     => :function,
368
          "validate_function" => fun_ref(
369
            method(:ValidateExpire),
370
            "boolean (string, map)"
371
          )
372
        },
373
        "umask"             => {
374
          "widget"      => :textentry,
375
          "valid_chars" => "01234567",
376
          # text entry
377
          "label"       => _("&Umask for Home Directory"),
378
          "no_help"     => true
379
        },
380
        "inactive"          => {
381
          "widget"  => :intfield,
382
          "opt"     => [:hstretch],
383
          # intfield
384
          "label"   => _(
385
            "Days &after Password Expiration Login Is Usable"
386
          ),
387
          "minimum" => -1,
388
          "no_help" => true
389
        },
390
        # widgets for authentication settings tab ------------------------------
391
        "auth_global"       => {
392
          "widget"        => :custom,
393
          "help"          => AuthentizationDialogHelp(),
394
          "init"          => fun_ref(method(:InitAuthData), "void (string)"),
395
          "store"         => fun_ref(
396
            method(:StoreAuthData),
397
            "void (string, map)"
398
          ),
399
          "handle"        => fun_ref(
400
            method(:HandleAuthData),
401
            "symbol (string, map)"
402
          ),
403
          "custom_widget" => VBox(
404
            RichText(Id("auth_summary"), ""),
405
            VSpacing(0.5),
406
            ReplacePoint(
407
              Id(:rpbutton),
408
              # menu button label
409
              MenuButton(Opt(:key_F4), _("&Configure..."), [])
410
            )
411
          ),
412
          "handle_events" => ["sssd", "nis", "samba"]
413
        }
414
      }
415
    end
416

417
    # Popup for choosing the password encryption method.
418
    #
419
    def EncryptionPopup
1✔
420
      method = Users.EncryptionMethod
×
421

422
      # Help text for password expert dialog 1/5
423
      help_text = _(
×
424
        "<p>\n" +
425
          "<b>This is for experts only.</b>\n" +
426
          "</p>"
427
      )
428

429
      # Help text for password expert dialog 2/5
430
      help_text = Ops.add(
×
431
        help_text,
432
        _(
433
          "<p>\n" +
434
            "Choose a password encryption method for local and system users.\n" +
435
            "<b>DES</b>, the Linux default method, works in all network environments, but it\n" +
436
            "restricts passwords to eight characters or less.\n" +
437
            "</p>\n"
438
        )
439
      )
440

441
      # Help text for password expert dialog 3/5
442
      help_text = Ops.add(
×
443
        help_text,
444
        _(
445
          "<p>\n" +
446
            "<b>MD5</b> allows longer passwords, so provides more security, but some\n" +
447
            "network protocols do not support this and you may have problems with NIS.\n" +
448
            "</p>"
449
        )
450
      )
451

452
      # Help text for password expert dialog 4/5
453
      help_text = Ops.add(
×
454
        help_text,
455
        _(
456
          "<p><b>SHA-512</b> is the current standard hash method. Using other algorithms is not recommended unless needed for compatibility purposes.</p>"
457
        )
458
      )
459

460
      UI.OpenDialog(
×
461
        VBox(
462
          # Label
463
          Heading(_("Password Encryption")),
464
          VSpacing(0.7),
465
          HBox(
466
            HSpacing(2),
467
            # frame label
468
            RadioButtonGroup(
469
              Id(:methods),
470
              Frame(
471
                _("Encryption Type"),
472
                HBox(
473
                  HSpacing(),
474
                  VBox(
475
                    VSpacing(0.5),
476
                    # Radio buttons for password encryption: DES-crypt
477
                    Left(RadioButton(Id("des"), _("&DES"), method == "des")),
478
                    # Radio buttons for password encryption: MD5-crypt
479
                    Left(RadioButton(Id("md5"), _("&MD5"), method == "md5")),
480
                    # Radio buttons for password encryption: sha256 crypt
481
                    Left(
482
                      RadioButton(
483
                        Id("sha256"),
484
                        _("SHA-&256"),
485
                        method == "sha256"
486
                      )
487
                    ),
488
                    # Radio buttons for password encryption: sha512 crypt
489
                    Left(
490
                      RadioButton(
491
                        Id("sha512"),
492
                        _("SHA-&512"),
493
                        method == "sha512"
494
                      )
495
                    ),
496
                    VSpacing(0.5)
497
                  )
498
                )
499
              )
500
            ),
501
            HSpacing(2)
502
          ),
503
          VSpacing(0.5),
504
          HBox(
505
            HStretch(),
506
            HWeight(
507
              1,
508
              PushButton(Id(:ok), Opt(:default, :key_F10), Label.OKButton)
509
            ),
510
            HStretch(),
511
            HWeight(
512
              1,
513
              PushButton(Id(:cancel), Opt(:key_F9), Label.CancelButton)
514
            ),
515
            HStretch(),
516
            HWeight(1, PushButton(Id(:help), Opt(:key_F2), Label.HelpButton)),
517
            HStretch()
518
          )
519
        )
520
      )
521

522
      button = nil
×
523
      begin
×
524
        button = UI.UserInput
×
525

526
        if button == :help
×
527
          Wizard.ShowHelp(help_text)
×
528
        elsif button == :ok
×
529
          method = Convert.to_string(
×
530
            UI.QueryWidget(Id(:methods), :CurrentButton)
531
          )
532
          Builtins.y2milestone("Changing encryption method to %1", method)
×
533
        end
534
      end while button != :ok && button != :cancel
535

536
      UI.CloseDialog
×
537
      method
×
538
    end
539

540
    # NIS server enabled together with non-DES encryption of passwords
541
    # In these popup, ask user what to do.
542
    def AskForNISServerEncryptionPopup(encr)
1✔
543
      ret = :ok
×
544

545
      # help text 1/3
546
      text = _(
×
547
        "<p>\nYou have changed the default encryption for user passwords.</p>"
548
      ) +
549
        # help text 2/3
550
        _(
551
          "<p>It seems that you are running a NIS server. In some network environments,\n" +
552
            "you might be unable to log in to a NIS client when a user password is\n" +
553
            "encrypted with a method other than DES.\n" +
554
            "</p>\n"
555
        ) +
556
        # help text 3/3
557
        _("<p>Really use the selected method?</p>")
558

559
      UI.OpenDialog(
×
560
        Opt(:decorated),
561
        HBox(
562
          VSpacing(14),
563
          VBox(
564
            HSpacing(50),
565
            RichText(Id(:rt), text),
566
            CheckBox(Id(:ch), Opt(:notify), Message.DoNotShowMessageAgain),
567
            HBox(
568
              PushButton(Id(:ok), Opt(:key_F10), Label.YesButton),
569
              PushButton(Id(:no), Opt(:key_F9), Label.NoButton)
570
            )
571
          )
572
        )
573
      )
574
      begin
×
575
        ret = Convert.to_symbol(UI.UserInput)
×
576
      end while !Builtins.contains([:cancel, :ok, :no], ret)
577

578
      if ret != :cancel
×
579
        Users.SetAskNISServerNotDES(
×
580
          Convert.to_boolean(UI.QueryWidget(Id(:ch), :Value))
581
        )
582
      end
583
      UI.CloseDialog
×
584
      ret
×
585
    end
586

587
    # Popup for configuration user/group filter for making the LDAP search
588
    # @return modified?
589
    def LDAPSearchFilterPopup
1✔
590
      default_user_f = UsersLDAP.GetDefaultUserFilter
×
591
      default_group_f = UsersLDAP.GetDefaultGroupFilter
×
592

593
      user_f = UsersLDAP.GetCurrentUserFilter
×
594
      group_f = UsersLDAP.GetCurrentGroupFilter
×
595

596
      user_f = default_user_f if user_f == ""
×
597
      group_f = default_group_f if group_f == ""
×
598

599
      ret = false
×
600

601
      # attributes are listed here, because during filter editing, the connection
602
      # to LDAP server doesn't have to be run yet
603
      user_attributes = [
604
        "objectClass",
×
605
        "loginShell",
606
        "gecos",
607
        "description",
608
        "cn",
609
        "uid",
610
        "uidNumber",
611
        "gidNumber",
612
        "homeDirectory",
613
        "shadowLastChange",
614
        "shadowMin",
615
        "shadowMax",
616
        "shadowWarning",
617
        "shadowInactive",
618
        "shadowExpire",
619
        "shadowFlag",
620
        "audio",
621
        "businessCategory",
622
        "carLicense",
623
        "departmentNumber",
624
        "displayName",
625
        "employeeNumber",
626
        "employeeType",
627
        "givenName",
628
        "homePhone",
629
        "homePostalAddress",
630
        "initials",
631
        "jpegPhoto",
632
        "labeledUri",
633
        "mail",
634
        "manager",
635
        "mobile",
636
        "o",
637
        "pager",
638
        "photo",
639
        "roomNumber",
640
        "secretary",
641
        "userCertificate",
642
        "x500uniqueIdentifier",
643
        "preferredLanguage",
644
        "userSMIMECertificate",
645
        "userPKCS12",
646
        "title",
647
        "x121Address",
648
        "registeredAddress",
649
        "destinationIndicator",
650
        "preferredDeliveryMethod",
651
        "telexNumber",
652
        "teletexTerminalIdentifier",
653
        "telephoneNumber",
654
        "internationalISDNNumber",
655
        "facsimileTelephoneNumber",
656
        "street",
657
        "postOfficeBox",
658
        "postalCode",
659
        "postalAddress",
660
        "physicalDeliveryOfficeName",
661
        "ou",
662
        "st",
663
        "l",
664
        "seeAlso",
665
        "sn"
666
      ]
667
      group_attributes = [
668
        "objectClass",
×
669
        "memberUid",
670
        "description",
671
        "gidNumber",
672
        "businessCategory",
673
        "seeAlso",
674
        "owner",
675
        "ou",
676
        "o",
677
        "member",
678
        "cn"
679
      ]
680

681
      connectives = [
682
        # combo box item
683
        Item(Id("and"), _("AND")),
×
684
        # combo box item
685
        Item(Id("or"), _("OR"))
686
      ]
687
      equality = ["=", "~=", "<=", ">="]
×
688
      curr_shown = UsersCache.GetCurrentSummary == "users" ? :users : :groups
×
689

690
      help_text =
691
        # helptext 1/4 - caption
692
        _("<p><b>LDAP Search Filter Changes</b></p>") +
×
693
          # helptext 2/4
694
          _(
695
            "<p>Here, extend the search filters for users and groups beyond the default search filters.</p>"
696
          ) +
697
          # helptext 3/4
698
          _(
699
            "<p>With <b>Default</b>, load the default filter from the user and group\n" +
700
              "configuration modules saved on the LDAP server (values of 'suseSearchFilter' attributes).\n" +
701
              "If you are not connected yet, you are prompted for the password.</p>\n"
702
          ) +
703
          # helptext 4/4 (do not translate the value (written as <tt> font))
704
          _(
705
            "<p><b>Example:</b>\n" +
706
              "<br>With the user filter\n" +
707
              "<br>\n" +
708
              "<tt>(&(objectClass=posixAccount)(uid=u*))</tt>\n" +
709
              "<br>\n" +
710
              "only obtain users with a username beginning with 'u'.</p>\n"
711
          )
712

713

714
      contents = HBox(
×
715
        HSpacing(1.5),
716
        VBox(
717
          HSpacing(70), # max 65 with help on left side...
718
          VSpacing(0.5),
719
          Left(
720
            RadioButtonGroup(
721
              VBox(
722
                Left(
723
                  RadioButton(
724
                    Id(:users),
725
                    Opt(:notify),
726
                    # radiobutton label
727
                    _("Search Filter for &Users"),
728
                    curr_shown == :users
729
                  )
730
                ),
731
                Left(
732
                  RadioButton(
733
                    Id(:groups),
734
                    Opt(:notify),
735
                    # radiobutton label
736
                    _("Search Filter for &Groups"),
737
                    curr_shown == :groups
738
                  )
739
                )
740
              )
741
            )
742
          ),
743
          TextEntry(Id(:currf), "", curr_shown == :users ? user_f : group_f),
×
744
          VSpacing(0.5),
745
          # frame label
746
          Frame(
747
            _("New Condition for Current Filter"),
748
            HBox(
749
              HSpacing(0.5),
750
              VBox(
751
                Left(ComboBox(Id(:andor), "", connectives)),
752
                HBox(
753
                  ReplacePoint(
754
                    Id(:rpa),
755
                    # combobox label
756
                    ComboBox(
757
                      Id(:atrs),
758
                      Opt(:editable),
759
                      _("&Attribute"),
760
                      curr_shown == :users ? user_attributes : group_attributes
×
761
                    )
762
                  ),
763
                  HSpacing(),
764
                  VBox(Label(""), ComboBox(Id(:eq), "", equality)),
765
                  HSpacing(),
766
                  # textentry label
767
                  TextEntry(Id(:val), _("&Value"), "")
768
                ),
769
                # pushbuttton label
770
                Right(PushButton(Id(:addu), _("A&dd to Filter")))
771
              ),
772
              HSpacing(0.5)
773
            )
774
          ),
775
          VSpacing(),
776
          HBox(
777
            PushButton(Id(:ok), Opt(:default, :key_F10), Label.OKButton),
778
            PushButton(Id(:cancel), Opt(:key_F9), Label.CancelButton),
779
            PushButton(Id(:help), Opt(:key_F2), Label.HelpButton),
780
            # Pushbutton label
781
            PushButton(Id(:read), Opt(:key_F3), _("De&fault"))
782
          ),
783
          VSpacing(0.5)
784
        ),
785
        HSpacing(1.5)
786
      )
787

788
      UI.OpenDialog(Opt(:decorated), contents)
×
789
      button = :notnext
×
790
      begin
×
791
        button = Convert.to_symbol(UI.UserInput)
×
792

793
        if button == :help
×
794
          Wizard.ShowHelp(help_text)
×
795
          next
×
796
        end
797
        if button == :read
×
798
          if Ldap.bind_pass == nil
×
799
            Ldap.SetBindPassword(Ldap.GetLDAPPassword(true))
×
800
          end
801
          if Ldap.bind_pass != nil && UsersLDAP.ReadFilters == ""
×
802
            UI.ChangeWidget(
×
803
              Id(:currf),
804
              :Value,
805
              curr_shown == :users ?
×
806
                UsersLDAP.GetDefaultUserFilter :
807
                UsersLDAP.GetDefaultGroupFilter
808
            )
809
          end
810
          next
×
811
        end
812
        curr_f = Convert.to_string(UI.QueryWidget(Id(:currf), :Value))
×
813
        if button == :addu
×
814
          if Convert.to_string(UI.QueryWidget(Id(:val), :Value)) == ""
×
815
            # error popup
816
            Popup.Error(_("Enter the value for the attribute."))
×
817
            UI.SetFocus(Id(:val))
×
818
            next
×
819
          end
820
          new_value = Builtins.sformat(
×
821
            "%1%2%3",
822
            Convert.to_string(UI.QueryWidget(Id(:atrs), :Value)),
823
            Convert.to_string(UI.QueryWidget(Id(:eq), :Value)),
824
            Convert.to_string(UI.QueryWidget(Id(:val), :Value))
825
          )
826

827
          conn = Convert.to_string(UI.QueryWidget(Id(:andor), :Value))
×
828
          UI.ChangeWidget(
×
829
            Id(:currf),
830
            :Value,
831
            UsersLDAP.AddToFilter(curr_f, new_value, conn)
832
          )
833
        end
834
        if button == :ok || button == :users || button == :groups
×
835
          if (button == :groups || button == :ok && curr_shown == :users) &&
×
836
              user_f != curr_f
837
            curr_user_f = curr_f
×
838
            if curr_user_f == ""
×
839
              # error popup
840
              Popup.Error(_("Enter the value of the user filter."))
×
841
              UI.SetFocus(Id(:currf))
×
842
              button = :notnext
×
843
              next
×
844
            end
845
            if !Builtins.issubstring(
×
846
                Builtins.tolower(curr_user_f),
847
                Builtins.tolower(default_user_f)
848
              ) &&
849
                # yes/no popup question
850
                !Popup.YesNo(
851
                  _(
852
                    "The new user filter does not contain the default user filter.\nReally use it?\n"
853
                  )
854
                )
855
              UI.SetFocus(Id(:currf))
×
856
              button = :notnext
×
857
              next
×
858
            end
859
            user_f = curr_user_f
×
860
          end
861
          if (button == :users || button == :ok && curr_shown == :groups) &&
×
862
              group_f != curr_f
863
            curr_group_f = curr_f
×
864
            if curr_group_f == ""
×
865
              # error popup
866
              Popup.Error(_("Enter the value of the group filter."))
×
867
              UI.SetFocus(Id(:currf))
×
868
              button = :notnext
×
869
              next
×
870
            end
871
            if !Builtins.issubstring(
×
872
                Builtins.tolower(curr_group_f),
873
                Builtins.tolower(default_group_f)
874
              )
875
              # yes/no popup question
876
              if !Popup.YesNo(
×
877
                  _(
878
                    "The new group filter does not contain the default group filter.\nReally use it?\n"
879
                  )
880
                )
881
                UI.SetFocus(Id(:currf))
×
882
                button = :notnext
×
883
                next
×
884
              end
885
            end
886
            group_f = curr_group_f
×
887
          end
888
          if button == :ok
×
889
            # checks are OK, let's update the values now
890
            if user_f != UsersLDAP.GetCurrentUserFilter
×
891
              UsersLDAP.SetCurrentUserFilter(user_f)
×
892
              ret = true
×
893
            end
894
            if group_f != UsersLDAP.GetCurrentGroupFilter
×
895
              UsersLDAP.SetCurrentGroupFilter(group_f)
×
896
              ret = true
×
897
            end
898
          else
899
            UI.ChangeWidget(Id(curr_shown), :Value, false)
×
900
            curr_shown = curr_shown == :users ? :groups : :users
×
901
            UI.ChangeWidget(Id(curr_shown), :Value, true)
×
902
            UI.ChangeWidget(
×
903
              Id(:currf),
904
              :Value,
905
              curr_shown == :users ? user_f : group_f
×
906
            )
907
            UI.ReplaceWidget(
×
908
              Id(:rpa),
909
              # combobox label
910
              ComboBox(
911
                Id(:atrs),
912
                Opt(:editable),
913
                _("&Attribute"),
914
                curr_shown == :users ? user_attributes : group_attributes
×
915
              )
916
            )
917
          end
918
        end
919
      end while button != :ok && button != :cancel
920

921
      UI.CloseDialog
×
922
      ret
×
923
    end
924

925
    # Popup for Login settings (Auotolgin feature, login without passwords)
926
    # @return modified?
927
    #
928
    def AutologinPopup
1✔
929
      help_text =
930
        # helptext 0/3 - caption
931
        _("<p><b>Login Settings</b></p>") +
×
932
          # helptext 1/3 - general info
933
          _(
934
            "<p>\n" +
935
              "The features described below are only available if you are using KDM or GDM as the login manager.\n" +
936
              "</p>\n"
937
          ) +
938
          # helptext 2/3
939
          _(
940
            "<p><b>Auto Login</b><br>\nBy setting <b>Auto Login</b>, skip the login procedure. The user chosen from the list is logged in automatically.</p>\n"
941
          ) +
942
          # helptext 3/3
943
          _(
944
            "<p><b>Passwordless Logins</b><br>\n" +
945
              "If this option is checked, all users are allowed to log in without entering\n" +
946
              "passwords. Otherwise, you are asked for the password even if you set a user to log in automatically.</p>\n"
947
          )
948

949

950
      ret = false
×
951

952
      user = Autologin.user
×
953
      pw_less = Autologin.pw_less
×
954
      auto_used = user != ""
×
955

956
      # TODO check if nis/ldap users were read?
957

958
      usernames = UsersCache.GetUsernames("local")
×
959

960
      UI.OpenDialog(
×
961
        Opt(:decorated),
962
        HBox(
963
          HSpacing(1.5),
964
          VBox(
965
            HSpacing(40),
966
            VSpacing(0.5),
967
            # dialog label
968
            Heading(_("Display Manager Login Settings")),
969
            HBox(
970
              HSpacing(0.5),
971
              VBox(
972
                VSpacing(0.5),
973
                Left(
974
                  CheckBox(
975
                    Id(:auto),
976
                    Opt(:notify),
977
                    # checkbox label
978
                    _("&Auto Login"),
979
                    auto_used
980
                  )
981
                ),
982
                VSpacing(0.2),
983
                HBox(
984
                  HSpacing(4), # move text under the checkbox
985
                  Left(
986
                    ComboBox(
987
                      Id(:autouser),
988
                      # textentry label
989
                      _("&User to Log In"),
990
                      usernames
991
                    )
992
                  )
993
                ),
994
                VSpacing(0.5),
995
                Left(
996
                  CheckBox(
997
                    Id(:pw_less),
998
                    # checkbox label
999
                    _("Password&less Logins"),
1000
                    pw_less
1001
                  )
1002
                ),
1003
                VSpacing(0.5)
1004
              ),
1005
              HSpacing(0.5)
1006
            ),
1007
            VSpacing(0.5),
1008
            HBox(
1009
              PushButton(Id(:ok), Opt(:default, :key_F10), Label.OKButton),
1010
              PushButton(Id(:cancel), Opt(:key_F9), Label.CancelButton),
1011
              PushButton(Id(:help), Opt(:key_F2), Label.HelpButton)
1012
            ),
1013
            VSpacing(0.5)
1014
          ),
1015
          HSpacing(1.5)
1016
        )
1017
      )
1018

1019
      UI.ChangeWidget(Id(:autouser), :Value, user) if user != ""
×
1020
      UI.ChangeWidget(Id(:autouser), :Enabled, auto_used)
×
1021

1022
      button = nil
×
1023
      begin
×
1024
        button = Convert.to_symbol(UI.UserInput)
×
1025

1026
        Wizard.ShowHelp(help_text) if button == :help
×
1027
        if button == :auto
×
1028
          auto_used = Convert.to_boolean(UI.QueryWidget(Id(:auto), :Value))
×
1029
          UI.ChangeWidget(Id(:autouser), :Enabled, auto_used)
×
1030
        end
1031
      end while !Builtins.contains([:ok, :cancel, :abort], button)
1032

1033
      if button == :ok
×
1034
        user = auto_used ?
×
1035
          Convert.to_string(UI.QueryWidget(Id(:autouser), :Value)) :
1036
          ""
1037
        pw_less = Convert.to_boolean(UI.QueryWidget(Id(:pw_less), :Value))
×
1038

1039
        if user != Autologin.user || pw_less != Autologin.pw_less
×
1040
          ret = true
×
1041
          Autologin.used = auto_used
×
1042
          Autologin.user = user
×
1043
          Autologin.pw_less = pw_less
×
1044
          Autologin.modified = true
×
1045
        end
1046
      end
1047
      UI.CloseDialog
×
1048
      ret
×
1049
    end
1050

1051

1052
    # Popup for deleting user
1053
    # @return [Symbol] for sequencer
1054
    def DeleteUserPopup
1✔
1055
      delete = true
×
1056
      delete_home = false
×
1057

1058
      type = UsersCache.GetUserType
×
1059
      user = Users.GetCurrentUser
×
1060
      username = Ops.get_string(user, "uid", "")
×
1061
      home = Ops.get_string(
×
1062
        user,
1063
        ["org_user", "homeDirectory"],
1064
        Ops.get_string(
1065
          user,
1066
          "org_homeDirectory",
1067
          Ops.get_string(user, "homeDirectory", "")
1068
        )
1069
      )
1070
      uid = -1
×
1071
      uid_a = Ops.get_string(
×
1072
        user,
1073
        ["org_user", "uidNumber"],
1074
        Ops.get_string(
1075
          user,
1076
          "org_uidNumber",
1077
          Ops.get_string(user, "uidNumber", "-1")
1078
        )
1079
      )
1080
      if Ops.is_string?(uid_a)
×
1081
        uid = Builtins.tointeger(uid_a)
×
1082
      else
1083
        uid = Convert.to_integer(uid_a)
×
1084
      end
1085

1086
      if type == "nis"
×
1087
        # error popup
1088
        Report.Message(
×
1089
          Builtins.sformat(
1090
            _("Cannot delete the user %1. It must be done on the NIS server."),
1091
            username
1092
          )
1093
        )
1094
        return nil
×
1095
      end
1096

1097
      if UserLogged(username) &&
×
1098
        # Continue/Cancel popup
1099
        !Popup.ContinueCancel(_("The user seems to be currently logged in.
1100
Continue anyway?"))
1101
        delete = false
×
1102
        return nil
×
1103
      end
1104

1105
      no_home = false
×
1106
      # check if dir exists with this owner
1107
      stat = Convert.to_map(SCR.Read(path(".target.stat"), home))
×
1108
      if type == "ldap" && !Ldap.file_server ||
×
1109
          Ops.get_integer(stat, "uid", -1) != uid
1110
        no_home = true
×
1111
      end
1112

1113
      # if the user want to delete a system user
1114
      if type == "system"
×
1115
        # yes-no popup headline
1116
        if !Popup.YesNoHeadline(
×
1117
            _("Selected User Is System User"),
1118
            # yes-no popup contents
1119
            _("Really delete this system user?")
1120
          )
1121
          delete = false
×
1122
        end
1123
      else
1124
        if home != "" && !no_home
×
1125
          contents = HBox(
×
1126
            HSpacing(3),
1127
            VBox(
1128
              VSpacing(1),
1129
              Left(
1130
                # question popup. %1 is username
1131
                Heading(Builtins.sformat(_("Delete the user %1?"), username))
1132
              ),
1133
              VSpacing(0.5),
1134
              Left(
1135
                CheckBox(
1136
                  Id(:delete_home),
1137
                  # checkbox label
1138
                  Builtins.sformat(_("Delete &Home Directory\n%1\n"), home)
1139
                )
1140
              ),
1141
              VSpacing(1),
1142
              HBox(
1143
                Bottom(PushButton(Id(:ok), Opt(:key_F10), Label.YesButton)),
1144
                Bottom(PushButton(Id(:cancel), Opt(:key_F9), Label.NoButton))
1145
              )
1146
            ),
1147
            HSpacing(3)
1148
          )
1149

1150
          UI.OpenDialog(Opt(:decorated), contents)
×
1151
          ret = UI.UserInput
×
1152
          delete = false if ret != :ok
×
1153
          delete_home = Convert.to_boolean(
×
1154
            UI.QueryWidget(Id(:delete_home), :Value)
1155
          )
1156

1157
          UI.CloseDialog
×
1158
        else
1159
          # yes-no popup. %1 is username
1160
          if !Popup.YesNo(
×
1161
              Builtins.sformat(_("\nReally delete the user %1?\n"), username)
1162
            )
1163
            delete = false
×
1164
          end
1165
        end
1166
      end
1167
      if delete
×
1168
        Users.DeleteUser(delete_home)
×
1169
        return :delete
×
1170
      end
1171
      nil
1172
    end
1173

1174
    # Popup for deleting group
1175
    # @return [Symbol] for sequencer
1176
    def DeleteGroupPopup
1✔
1177
      delete = true
×
1178
      type = UsersCache.GetGroupType
×
1179
      group = Users.GetCurrentGroup
×
1180
      member_attribute = UsersLDAP.GetMemberAttribute
×
1181

1182
      # if no user is in this group
1183
      if Ops.get_map(group, "userlist", {}) == {} &&
×
1184
          Ops.get_map(group, "more_users", {}) == {} &&
1185
          Ops.get_map(group, member_attribute, {}) == {}
1186
        #if the group is a system group ask the user ..
1187
        if type == "system"
×
1188
          # yes-no popup headline
1189
          if !Popup.YesNoHeadline(
×
1190
              _("System Group"),
1191
              #/ yes-no popup contents
1192
              _("Really delete this system group?")
1193
            )
1194
            return nil
×
1195
          end
1196
        else
1197
          # yes-no popup, %1 si group name
1198
          if !Popup.YesNo(
×
1199
              Builtins.sformat(
1200
                _("\nReally delete the group %1?\n"),
1201
                Ops.get_string(group, "cn", "")
1202
              )
1203
            )
1204
            return nil
×
1205
          end
1206
        end
1207
      else
1208
        # warning popup
1209
        Popup.Warning(
×
1210
          _(
1211
            "You cannot delete this group because\n" +
1212
              "there are users in the group.\n" +
1213
              "Remove these users from the group first.\n"
1214
          )
1215
        )
1216
        return nil
×
1217
      end
1218

1219
      Users.DeleteGroup
×
1220
      :delete
×
1221
    end
1222

1223
    # Dialog for definition of customized view
1224
    # @param [String] what "users" or "groups"
1225
    # @return true if customs were odified
1226
    def CustomizePopup(what)
1✔
1227
      view = VBox()
×
1228
      label = ""
×
1229
      sets = []
×
1230
      custom_sets = []
×
1231
      set_to_string = {}
×
1232

1233
      if what == "users"
×
1234
        sets = Builtins.filter(Users.GetAvailableUserSets) do |set|
×
1235
          set != "custom"
×
1236
        end
1237
        custom_sets = Users.GetUserCustomSets
×
1238
        set_to_string = deep_copy(@userset_to_string)
×
1239
        # Frame label
1240
        label = _("User List View")
×
1241
      else
1242
        sets = Builtins.filter(Users.GetAvailableGroupSets) do |set|
×
1243
          set != "custom"
×
1244
        end
1245
        custom_sets = Users.GetGroupCustomSets
×
1246
        set_to_string = deep_copy(@groupset_to_string)
×
1247
        # Frame label
1248
        label = _("Group List View")
×
1249
      end
1250

1251
      Builtins.foreach(sets) do |set|
×
1252
        view = Builtins.add(view, VSpacing(0.5))
×
1253
        if Builtins.contains(custom_sets, set)
×
1254
          view = Builtins.add(
×
1255
            view,
1256
            Left(
1257
              CheckBox(Id(set), Ops.get_string(set_to_string, set, ""), true)
1258
            )
1259
          )
1260
        else
1261
          view = Builtins.add(
×
1262
            view,
1263
            Left(
1264
              CheckBox(Id(set), Ops.get_string(set_to_string, set, ""), false)
1265
            )
1266
          )
1267
        end
1268
      end
1269
      view = Builtins.add(view, VSpacing(0.5))
×
1270

1271
      UI.OpenDialog(
×
1272
        Opt(:decorated),
1273
        HBox(
1274
          HSpacing(1.5),
1275
          VBox(
1276
            HSpacing(40),
1277
            VSpacing(0.5),
1278
            Frame(label, view),
1279
            VSpacing(0.5),
1280
            HBox(
1281
              PushButton(Id(:ok), Opt(:default, :key_F10), Label.OKButton),
1282
              PushButton(Id(:cancel), Opt(:key_F9), Label.CancelButton)
1283
            ),
1284
            VSpacing(0.5)
1285
          ),
1286
          HSpacing(1.5)
1287
        )
1288
      )
1289
      ret = UI.UserInput
×
1290
      modified = false
×
1291
      new_customs = []
×
1292
      Builtins.foreach(sets) do |set|
1293
        if Convert.to_boolean(UI.QueryWidget(Id(set), :Value))
×
1294
          new_customs = Builtins.add(new_customs, set)
×
1295
          modified = true if !Builtins.contains(custom_sets, set)
×
1296
        else
1297
          modified = true if Builtins.contains(custom_sets, set)
×
1298
        end
1299
      end if ret == :ok
×
1300
      UI.CloseDialog
×
1301
      if modified
×
1302
        if Builtins.contains(new_customs, "ldap") && Ldap.bind_pass == nil
×
1303
          Ldap.SetBindPassword(Ldap.GetLDAPPassword(true))
×
1304
          if Ldap.bind_pass == nil || UsersLDAP.ReadSettings != ""
×
1305
            new_customs = Builtins.filter(new_customs) { |set| set != "ldap" }
×
1306
          end
1307
        end
1308
        modified = Users.ChangeCustoms(what, new_customs)
×
1309
      end
1310
      modified
×
1311
    end
1312

1313
    # When there are more users/groups shown, choose which type should be created
1314
    # after `add click
1315
    def ChooseTypePopup(sets, what)
1✔
1316
      sets = deep_copy(sets)
×
1317
      set_to_string = {
1318
        # type of user/group
1319
        # (item of list with the headline 'Choose the type of user to add')
1320
        "local"  => _(
×
1321
          "Local"
1322
        ),
1323
        # type of user/group
1324
        # (item of list with the headline 'Choose the type of user to add')
1325
        "ldap"   => _(
1326
          "LDAP"
1327
        ),
1328
        # type of user/group
1329
        # (item of list with the headline 'Choose the type of user to add')
1330
        "system" => _(
1331
          "System"
1332
        )
1333
      }
1334

1335
      sets = Builtins.filter(sets) { |set| set != "nis" }
×
1336
      ret = Ops.get(sets, 0, "local")
×
1337
      label = what == "user" ?
×
1338
        # label
1339
        _("User Type") :
1340
        # label
1341
        _("Group Type")
1342

1343
      return ret if Ops.less_than(Builtins.size(sets), 2)
×
1344

1345
      rbs = VBox()
×
1346
      Builtins.foreach(sets) do |set|
×
1347
        rbs = Builtins.add(
×
1348
          rbs,
1349
          Left(
1350
            RadioButton(
1351
              Id(set),
1352
              Ops.get_string(set_to_string, set, set),
1353
              set == ret
1354
            )
1355
          )
1356
        )
1357
      end
1358

1359
      UI.OpenDialog(
×
1360
        Opt(:decorated),
1361
        HBox(
1362
          HSpacing(1.5),
1363
          VBox(
1364
            HSpacing(40),
1365
            VSpacing(0.5),
1366
            Left(Label(label)),
1367
            VSpacing(0.5),
1368
            Left(RadioButtonGroup(rbs)),
1369
            VSpacing(0.5),
1370
            HBox(
1371
              PushButton(Id(:ok), Opt(:default, :key_F10), Label.OKButton),
1372
              PushButton(Id(:cancel), Opt(:key_F9), Label.CancelButton)
1373
            ),
1374
            VSpacing(0.5)
1375
          ),
1376
          HSpacing(1.5)
1377
        )
1378
      )
1379

1380
      r = UI.UserInput
×
1381

1382
      Builtins.foreach(sets) do |set|
×
1383
        ret = set if Convert.to_boolean(UI.QueryWidget(Id(set), :Value))
×
1384
      end
1385

1386
      UI.CloseDialog
×
1387

1388
      return "" if r == :cancel
×
1389

1390
      ret
×
1391
    end
1392

1393

1394
    #================================================================
1395

1396
    def GetSetsItems(set)
1✔
1397
      items = []
×
1398
      if set == "users"
×
1399
        Builtins.foreach(Users.GetAvailableUserSets) do |set2|
×
1400
          items = Builtins.add(
×
1401
            items,
1402
            Item(Id(set2), Ops.get_string(@userset_to_string, set2, ""))
1403
          )
1404
        end
1405
        # menubutton item
1406
        items = Builtins.add(
×
1407
          items,
1408
          Item(Id(:customize), _("Customi&ze Filter..."))
1409
        )
1410
      else
1411
        Builtins.foreach(Users.GetAvailableGroupSets) do |set2|
×
1412
          items = Builtins.add(
×
1413
            items,
1414
            Item(Id(set2), Ops.get_string(@groupset_to_string, set2, ""))
1415
          )
1416
        end
1417
        # menubutton item
1418
        items = Builtins.add(
×
1419
          items,
1420
          Item(Id(:customize), _("Customi&ze Filter..."))
1421
        )
1422
      end
1423
      deep_copy(items)
×
1424
    end
1425

1426
    # return the list of menu items of "Expert Options" menubutton
1427
    def GetExpertList
1✔
1428
      expert_list = []
×
1429
      if Autologin.available
×
1430
        expert_list = Builtins.add(
×
1431
          expert_list,
1432
          # menubutton label
1433
          Item(Id(:autologinconf), _("&Login Settings"))
1434
        )
1435
      end
1436
      if !Mode.config
×
1437
        expert_list = Builtins.prepend(
×
1438
          expert_list,
1439
          # menubutton label
1440
          Item(Id(:enc), _("Password &Encryption"))
1441
        )
1442
        if !Stage.cont
×
1443
          expert_list = Builtins.add(
×
1444
            expert_list,
1445
            # menubutton label
1446
            Item(Id(:save), _("&Write Changes Now"))
1447
          )
1448
        end
1449
      end
1450
      deep_copy(expert_list)
×
1451
    end
1452

1453
    # return the list of menu items for LDAP expert options
1454
    def GetLDAPExpertList
1✔
1455
      expert_list = []
×
1456
      if !Mode.config && Users.LDAPAvailable && !Users.LDAPModified
×
1457
        expert_list = Builtins.add(
×
1458
          expert_list,
1459
          # menubutton label
1460
          Item(Id(:ldapfilter), _("LDAP &Search Filter"))
1461
        )
1462
        expert_list = Builtins.add(
×
1463
          expert_list,
1464
          # menubutton label
1465
          Item(Id(:ldapconf), _("L&DAP User and Group Configuration"))
1466
        )
1467
      end
1468
      deep_copy(expert_list)
×
1469
    end
1470

1471
    #================================================================
1472
    #----------------- some help texts ------------------------------
1473

1474
    # First part of the help text.
1475
    # @return [String] help text
1476
    def help_main_start
1✔
1477
      # help text 1/1
1478
      _(
36✔
1479
        "<p>\n" +
1480
          "Linux is a multiuser system. Several different users can be logged in to the\n" +
1481
          "system at the same time.  To avoid confusion, each user must have\n" +
1482
          "a unique identity. Additionally, every user belongs to at least one group.\n" +
1483
          "</p>\n"
1484
      )
1485
    end
1486

1487

1488
    # Last part of the help text.
1489
    # @return [String] help text
1490
    def help_main_end
1✔
1491
      button = Stage.cont ? Label.NextButton : Label.FinishButton
36✔
1492

1493
      # help text 1/3
1494
      Ops.add(
36✔
1495
        _(
1496
          "<p>\n" +
1497
            "Users and groups are arranged in various sets. Change the set currently shown in the table with <b>Set Filter</b>.\n" +
1498
            "Customize your view with <b>Customize Filter</b>.</p>\n"
1499
        ) +
1500
          # help text 2/3
1501
          _(
1502
            "<p>\n" +
1503
              "Click <b>Expert Options</b> to edit various expert settings, such as\n" +
1504
              "password encryption type, user authentication method, default values for new\n" +
1505
              "users, or login settings. With <b>Write Changes Now</b>, save\n" +
1506
              "all changes made so far without exiting the configuration module.</p>\n"
1507
          ),
1508
        # help text 3/3, %1 is translated button label
1509
        Builtins.sformat(
1510
          _(
1511
            "<p>\n" +
1512
              "To save the modified user and group settings to your system, press\n" +
1513
              "<b>%1</b>.\n" +
1514
              "</p>\n"
1515
          ),
1516
          String.RemoveShortcut(button)
1517
        )
1518
      )
1519
    end
1520

1521
    # Help for UsersDialog.
1522
    # @return [String] help text
1523
    def UsersDialogHelp
1✔
1524
      # help text 1/4
1525
      Ops.add(
18✔
1526
        Ops.add(
1527
          Ops.add(
1528
            Ops.add(
1529
              Ops.add(
1530
                help_main_start,
1531
                _(
1532
                  "\n" +
1533
                    "<p>\n" +
1534
                    "Use this dialog to get information about existing users and add or modify\n" +
1535
                    "users.  \n" +
1536
                    "</p>\n"
1537
                )
1538
              ),
1539
              # help text 2/4
1540
              _(
1541
                "<p>\n" +
1542
                  "To shift to the group dialog, select <b>Groups</b>.\n" +
1543
                  "</p>\n"
1544
              )
1545
            ),
1546
            # help text 3/4
1547
            _(
1548
              "\n" +
1549
                "<p>\n" +
1550
                "To create a new user, click <b>Add</b>.\n" +
1551
                "</p>\n"
1552
            )
1553
          ),
1554
          # help text 4/4
1555
          _(
1556
            "<p>\n" +
1557
              "To edit or delete an existing user, select one user from the list and\n" +
1558
              "click <b>Edit</b> or <b>Delete</b>.\n" +
1559
              "</p>\n"
1560
          )
1561
        ),
1562
        help_main_end
1563
      )
1564
    end
1565

1566
    # Help for usersGroups.
1567
    # @return [String] help text
1568
    def GroupsDialogHelp
1✔
1569
      Ops.add(
18✔
1570
        Ops.add(
1571
          Ops.add(
1572
            Ops.add(
1573
              Ops.add(
1574
                help_main_start,
1575
                # help text 1/4
1576
                _(
1577
                  "\n" +
1578
                    "<p>\n" +
1579
                    "Use this dialog to get information about existing groups and add or modify groups.\n" +
1580
                    "</p>\n"
1581
                )
1582
              ),
1583
              # help text 2/4
1584
              _(
1585
                "<p>\n" +
1586
                  "To shift to the user dialog, select <b>Users</b>.\n" +
1587
                  "</p>\n"
1588
              )
1589
            ),
1590
            # help text 3/4
1591
            _(
1592
              "\n" +
1593
                "<p>\n" +
1594
                "To create a new group, click <b>Add</b>.\n" +
1595
                "</p>\n"
1596
            )
1597
          ),
1598
          # help text 4/4
1599
          _(
1600
            "<p>\n" +
1601
              "To edit or delete an existing group, select one group from the list and\n" +
1602
              "click <b>Edit</b> or <b>Delete</b>.\n" +
1603
              "</p>\n"
1604
          )
1605
        ),
1606
        help_main_end
1607
      )
1608
    end
1609

1610

1611
    #================================================================
1612

1613
    # Validation function for the default value of account expiration
1614
    def ValidateExpire(key, event)
1✔
1615
      event = deep_copy(event)
×
1616
      new_exp_date = Convert.to_string(UI.QueryWidget(Id(key), :Value))
×
1617

1618
      if new_exp_date != "" &&
×
1619
          !Builtins.regexpmatch(
1620
            new_exp_date,
1621
            "[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]"
1622
          )
1623
        # popup label - don't reorder the letters YYYY-MM-DD
1624
        # The date must stay in this format
1625
        Report.Error(_("The expiration date must be in the format YYYY-MM-DD."))
×
1626
        UI.SetFocus(Id(key))
×
1627
        return false
×
1628
      end
1629
      true
×
1630
    end
1631

1632
    # Validation function for the default home prefix
1633
    def ValidateHomePrefix(key, event)
1✔
1634
      event = deep_copy(event)
×
1635
      new_home = Convert.to_string(UI.QueryWidget(Id(key), :Value))
×
1636
      if SCR.Read(path(".target.dir"), new_home) == nil
×
1637
        if SCR.Read(path(".target.size"), new_home) != -1
×
1638
          # error message
1639
          Report.Error(
×
1640
            _(
1641
              "The entered path prefix for home is not a directory.\nTry again.\n"
1642
            )
1643
          )
1644
          UI.SetFocus(Id(key))
×
1645
          return false
×
1646
        else
1647
          # yes/no popup
1648
          if Popup.YesNo(
×
1649
              _("The selected directory does not exist.\nCreate it now?\n")
1650
            )
1651
            if !Convert.to_boolean(SCR.Execute(path(".target.mkdir"), new_home))
×
1652
              Report.Error(Message.UnableToCreateDirectory(new_home))
×
1653
              UI.SetFocus(Id(key))
×
1654
              return false
×
1655
            end
1656
          else
1657
            UI.SetFocus(Id(key))
×
1658
            return false
×
1659
          end
1660
        end
1661
      end
1662
      true
×
1663
    end
1664

1665
    def ValidateShell(key, event)
1✔
1666
      event = deep_copy(event)
×
1667
      new_shell = Convert.to_string(UI.QueryWidget(Id(key), :Value))
×
1668
      if !Builtins.contains(Users.AllShells, new_shell)
×
1669
        # Yes-No popup
1670
        return Popup.YesNo(
×
1671
          _(
1672
            "If you select a nonexistent shell, the user\nmay be unable to log in. Continue?\n"
1673
          )
1674
        )
1675
      end
1676
      true
×
1677
    end
1678

1679
    # Initialize all the values in the dialog with new user defaults
1680
    def InitDefaults(key)
1✔
1681
      defaults = Users.GetLoginDefaults
×
1682
      items = []
×
1683
      @all_groupnames = UsersCache.GetAllGroupnames
×
1684
      defaultgroup = Users.GetDefaultGroupname("local")
×
1685

1686
      Builtins.foreach(@all_groupnames) do |grouptype, groupmap|
×
1687
        # only local sets
1688
        next if !Builtins.contains(["local", "system"], grouptype)
×
1689
        Builtins.foreach(groupmap) do |group, val|
×
1690
          if group == defaultgroup
×
1691
            items = Builtins.add(items, Item(Id(group), group, true))
×
1692
          else
1693
            items = Builtins.add(items, Item(Id(group), group))
×
1694
          end
1695
        end
1696
      end
1697
      UI.ChangeWidget(Id("defaultgroup"), :Items, items)
×
1698
      UI.ChangeWidget(Id("shell"), :Items, Users.AllShells)
×
1699
      UI.ChangeWidget(Id("shell"), :Value, Users.GetDefaultShell("local"))
×
1700

1701
      UI.ChangeWidget(
×
1702
        Id("home"),
1703
        :Value,
1704
        Ops.get_string(defaults, "home", "/home")
1705
      )
1706

1707
      UI.ChangeWidget(
×
1708
        Id("inactive"),
1709
        :Value,
1710
        Builtins.tointeger(Ops.get_string(defaults, "inactive", "0"))
1711
      )
1712

1713
      expire = Ops.get_string(defaults, "expire", "")
×
1714
      exp_date = ""
×
1715
      if expire != "0" && expire != ""
×
1716
        # 'expire' is expected to be number of days since 1970-01-01
1717
        out = SCR.Execute(
×
1718
          path(".target.bash_output"),
1719
          "/usr/bin/date --date='1970-01-01 00:00:01 '#{expire.shellescape}' days' +\"%Y-%m-%d\""
1720
        )
1721
        exp_date = Builtins.deletechars(Ops.get_string(out, "stdout", ""), "\n")
×
1722
      end
1723
      UI.ChangeWidget(Id("expire"), :Value, exp_date)
×
1724
      UI.ChangeWidget(
×
1725
        Id("umask"),
1726
        :Value,
1727
        Ops.get_string(defaults, "umask", "")
1728
      )
1729
      UI.ChangeWidget(Id("umask"), :InputMaxLength, 3)
×
1730

1731
      nil
1732
    end
1733

1734
    # Store all the values from the dialog with new user defaults
1735
    # (when leaving the dialog)
1736
    def StoreDefaults(key, event)
1✔
1737
      event = deep_copy(event)
×
1738
      defaults = Users.GetLoginDefaults
×
1739
      new_defaults = {}
×
1740
      Builtins.foreach(["home", "shell", "inactive", "umask"]) do |key2|
×
1741
        val = UI.QueryWidget(Id(key2), :Value)
×
1742
        val = Builtins.sformat("%1", val) if Ops.is_integer?(val)
×
1743
        if Ops.get(defaults, key2) != val
×
1744
          Ops.set(new_defaults, key2, Convert.to_string(val))
×
1745
        end
1746
      end
1747

1748
      new_exp_date = Convert.to_string(UI.QueryWidget(Id("expire"), :Value))
×
1749
      new_expire = Ops.get_string(defaults, "expire", "")
×
1750
      if new_exp_date == ""
×
1751
        new_expire = ""
×
1752
      else
1753
        out = SCR.Execute(
×
1754
          path(".target.bash_output"),
1755
          "/usr/bin/date --date=#{new_exp_date.shellescape}' UTC' +%s"
1756
        )
1757
        seconds_s = Builtins.deletechars(
×
1758
          Ops.get_string(out, "stdout", "0"),
1759
          "\n"
1760
        )
1761
        if seconds_s != ""
×
1762
          days = Ops.divide(Builtins.tointeger(seconds_s), 60 * 60 * 24)
×
1763
          new_expire = Builtins.sformat("%1", days)
×
1764
        end
1765
      end
1766
      if new_expire != Ops.get_string(defaults, "expire", "")
×
1767
        Ops.set(new_defaults, "expire", new_expire)
×
1768
      end
1769

1770
      new_defgroup = Convert.to_string(
×
1771
        UI.QueryWidget(Id("defaultgroup"), :Value)
1772
      )
1773
      if Users.GetDefaultGroupname("local") != new_defgroup
×
1774
        g = Users.GetGroupByName(new_defgroup, "")
×
1775
        Ops.set(
×
1776
          new_defaults,
1777
          "group",
1778
          Builtins.sformat(
1779
            "%1",
1780
            GetInt(Ops.get(g, "gidNumber"), Users.GetDefaultGID("local"))
1781
          )
1782
        )
1783
      end
1784
      Users.SetLoginDefaults(new_defaults, new_defgroup) if new_defaults != {}
×
1785

1786
      nil
1787
    end
1788

1789
    # universal handler for directory browsing
1790
    def HandleBrowseDirectory(key, event)
1✔
1791
      event = deep_copy(event)
×
1792
      return nil if Ops.get(event, "ID") != key
×
1793
      val = Builtins.substring(key, 7)
×
1794
      current = Convert.to_string(UI.QueryWidget(Id(val), :Value))
×
1795
      current = "" if current == nil
×
1796
      # directory location popup label
1797
      dir = UI.AskForExistingDirectory(current, _("Path to Directory"))
×
1798
      UI.ChangeWidget(Id(val), :Value, dir) if dir != nil
×
1799
      nil
1800
    end
1801

1802

1803
    # Handle the switch between tabs (load set of items for users or groups)
1804
    def InitTabUsersGroups(widget_id)
1✔
1805
      current_summary = UsersCache.GetCurrentSummary
×
1806
      if current_summary == CWMTab.CurrentTab
×
1807
        # tab shows already current set
1808
        return
×
1809
      else
1810
        UsersCache.ChangeCurrentSummary
×
1811
      end
1812

1813
      nil
1814
    end
1815

1816
    # Initialize the contents of Summary Table widget
1817
    def SummaryTableInit(widget_id)
1✔
1818
      items = []
×
1819
      current_summary = UsersCache.GetCurrentSummary
×
1820
      if current_summary == "users"
×
1821
        items = UsersCache.GetUserItems
×
1822
        UI.ReplaceWidget(
×
1823
          Id(:rptable),
1824
          Table(
1825
            Id("table"),
1826
            Opt(:notify),
1827
            Header(
1828
              # table header
1829
              _("Login"),
1830
              # table header
1831
              _("Name"),
1832
              # table header
1833
              _("UID"),
1834
              # table header
1835
              _("Groups")
1836
            ),
1837
            []
1838
          )
1839
        )
1840
      else
1841
        items = UsersCache.GetGroupItems
×
1842
        UI.ReplaceWidget(
×
1843
          Id(:rptable),
1844
          Table(
1845
            Id("table"),
1846
            Opt(:notify),
1847
            Header(
1848
              # table header
1849
              _("Group Name"),
1850
              # table header
1851
              _("Group ID"),
1852
              # table header
1853
              _("Group Members")
1854
            ),
1855
            []
1856
          )
1857
        )
1858
      end
1859
      UI.ChangeWidget(Id(widget_id), :Items, items)
×
1860
      if Ops.greater_than(Builtins.size(items), 0)
×
1861
        UI.SetFocus(Id(widget_id))
×
1862
        focusline = UsersCache.GetCurrentFocus
×
1863
        if focusline != nil
×
1864
          UI.ChangeWidget(Id(widget_id), :CurrentItem, focusline)
×
1865
        end
1866
      end
1867
      UI.ReplaceWidget(
×
1868
        Id(:rpexpert),
1869
        # Menu Buton label
1870
        MenuButton(
1871
          Id(:expertlist),
1872
          _("E&xpert Options"),
1873
          Builtins.union(GetExpertList(), GetLDAPExpertList())
1874
        )
1875
      )
1876

1877
      nil
1878
    end
1879

1880
    # Handler for users/groups summary table
1881
    def HandleSummaryTable(widget_id, event)
1✔
1882
      event = deep_copy(event)
×
1883
      ev_id = Ops.get(event, "ID")
×
1884

1885
      current_summary = UsersCache.GetCurrentSummary
×
1886

1887
      ev_id = :edit if ev_id == "table"
×
1888
      if ev_id == :new
×
1889
        error = ""
×
1890
        if current_summary == "users"
×
1891
          current_users = Users.GetCurrentUsers
×
1892
          if Ops.greater_than(Builtins.size(current_users), 1)
×
1893
            set = ChooseTypePopup(current_users, "user")
×
1894
            return nil if set == ""
×
1895
            current_users = Builtins.filter(current_users) { |u| u != set }
×
1896
            current_users = Builtins.prepend(current_users, set)
×
1897
            Users.SetCurrentUsers(current_users)
×
1898
          end
1899
          error = Users.AddUser({})
×
1900
        else
1901
          current_groups = Users.GetCurrentGroups
×
1902
          if Ops.greater_than(Builtins.size(current_groups), 1)
×
1903
            set = ChooseTypePopup(current_groups, "group")
×
1904
            return nil if set == ""
×
1905
            current_groups = Builtins.filter(current_groups) { |u| u != set }
×
1906
            current_groups = Builtins.prepend(current_groups, set)
×
1907
            Users.SetCurrentGroups(current_groups)
×
1908
          end
1909
          error = Users.AddGroup({})
×
1910
        end
1911
        if error != ""
×
1912
          Popup.Error(error)
×
1913
          return nil
×
1914
        end
1915
      end
1916
      if ev_id == :edit || ev_id == :delete
×
1917
        selected = Convert.to_string(UI.QueryWidget(Id("table"), :CurrentItem))
×
1918
        if selected != nil
×
1919
          error = ""
×
1920
          UsersCache.SetCurrentFocus(selected)
×
1921
          if current_summary == "users"
×
1922
            Users.SelectUserByName(selected)
×
1923
            if ev_id == :delete
×
1924
              ev_id = DeleteUserPopup()
×
1925
            else
1926
              error = Users.EditUser({})
×
1927
            end
1928
          else
1929
            Users.SelectGroupByName(selected)
×
1930
            if UsersCache.GetGroupType == "nis"
×
1931
              # error popup
1932
              Report.Message(
×
1933
                _(
1934
                  "NIS groups can only be\nmodified and deleted on the server.\n"
1935
                )
1936
              )
1937
              ev_id = nil
×
1938
            end
1939

1940
            if ev_id == :delete
×
1941
              ev_id = DeleteGroupPopup()
×
1942
            else
1943
              error = Users.EditGroup({})
×
1944
            end
1945
          end
1946
          if error != ""
×
1947
            Report.Error(error)
×
1948
            return nil
×
1949
          end
1950
        else
1951
          # error popup
1952
          Report.Message(_("Select an entry from the table."))
×
1953
          return nil
×
1954
        end
1955
      end
1956
      if ev_id == :enc
×
1957
        enc = EncryptionPopup()
×
1958
        if enc != Users.EncryptionMethod
×
1959
          if enc != "des" && Users.NISMaster && !Users.NotAskNISServerNotDES
×
1960
            return nil if AskForNISServerEncryptionPopup(enc) != :ok
×
1961
          end
1962
          Users.SetEncryptionMethod(enc)
×
1963
        end
1964
        return nil
×
1965
      end
1966
      if ev_id == :autologinconf
×
1967
        AutologinPopup()
×
1968
        return nil
×
1969
      end
1970
      if ev_id == :save
×
1971
        if !Users.Modified
×
1972
          #popup message (user wants to save but there is no modification)
1973
          Popup.Message(_("There are no changes to save."))
×
1974
          return nil
×
1975
        end
1976
        Wizard.CreateDialog
×
1977
        Wizard.SetDesktopTitleAndIcon("org.opensuse.yast.Users")
×
1978
        ret = WriteDialog(true)
×
1979
        Wizard.CloseDialog
×
1980
        Builtins.y2milestone("WriteDialog returned %1", ret)
×
1981
        # LDAP expert options could be available again
1982
        SummaryTableInit("table")
×
1983
        return nil
×
1984
      end
1985
      if ev_id == :ldapfilter
×
1986
        # change of search filter (only when LDAP was not modified yet)
1987
        if LDAPSearchFilterPopup() && !Users.LDAPModified
×
1988
          Users.SetLDAPNotRead(true)
×
1989
          current = current_summary == "users" ?
×
1990
            Users.GetCurrentUsers :
1991
            Users.GetCurrentGroups
1992
          if Builtins.contains(current, "ldap")
×
1993
            # simulate the action "show LDAP users"
1994
            HandleFilterLine(widget_id, { "ID" => "ldap" })
×
1995
          end
1996
          # now update the other list (not current_summary)
1997
          current = current_summary == "users" ?
×
1998
            Users.GetCurrentGroups :
1999
            Users.GetCurrentUsers
2000
          if Builtins.contains(current, "ldap")
×
2001
            # customize view is lost... TODO
2002
            if current_summary == "users"
×
2003
              Users.ChangeCurrentGroups("ldap")
×
2004
            else
2005
              Users.ChangeCurrentUsers("ldap")
×
2006
            end
2007
          end
2008
        end
2009
        return nil
×
2010
      end
2011
      if ev_id == :ldapconf
×
2012
        if LdapAdministrationDialog() && Ldap.ldap_modified
×
2013
          if !Users.LDAPNotRead &&
×
2014
              # yes/no popup (data were changed)
2015
              Popup.YesNo(_("Reread all data from LDAP server?"))
2016
            # read all LDAP configuration again!
2017
            Users.SetLDAPNotRead(true)
×
2018
            UsersLDAP.SetFiltersRead(false)
×
2019
            UsersLDAP.SetInitialized(false)
×
2020
            current = current_summary == "users" ?
×
2021
              Users.GetCurrentUsers :
2022
              Users.GetCurrentGroups
2023
            if Builtins.contains(current, "ldap")
×
2024
              # simulate the action "show LDAP users"
2025
              HandleFilterLine(widget_id, { "ID" => "ldap" })
×
2026
            end
2027
            # now update the other list (not current_summary)
2028
            current = current_summary == "users" ?
×
2029
              Users.GetCurrentGroups :
2030
              Users.GetCurrentUsers
2031
            if Builtins.contains(current, "ldap")
×
2032
              # customize view is lost... TODO
2033
              if current_summary == "users"
×
2034
                Users.ChangeCurrentGroups("ldap")
×
2035
              else
2036
                Users.ChangeCurrentUsers("ldap")
×
2037
              end
2038
            end
2039
          end
2040
          Ldap.ldap_modified = false
×
2041
        end
2042
        return nil
×
2043
      end
2044
      if !Ops.is_symbol?(ev_id)
×
2045
        Builtins.y2error("strange ev_id value: %1", ev_id)
×
2046
        return nil
×
2047
      end
2048
      Convert.to_symbol(ev_id)
×
2049
    end
2050

2051
    # Initialize the value of the label with current filter and filter selection
2052
    def InitFilterLine(widget_id)
1✔
2053
      current_summary = UsersCache.GetCurrentSummary
×
2054
      curr = ""
×
2055
      if current_summary == "users"
×
2056
        if UsersCache.CustomizedUsersView
×
2057
          curr = Ops.get_string(@userset_to_label, "custom", "")
×
2058
        else
2059
          current_users = Users.GetCurrentUsers
×
2060
          curr = Ops.get_string(
×
2061
            @userset_to_label,
2062
            Ops.get_string(current_users, 0, "custom"),
2063
            ""
2064
          )
2065
        end
2066
      else
2067
        if UsersCache.CustomizedGroupsView
×
2068
          curr = Ops.get_string(@groupset_to_label, "custom", "")
×
2069
        else
2070
          current_groups = Users.GetCurrentGroups
×
2071
          curr = Ops.get_string(
×
2072
            @groupset_to_label,
2073
            Ops.get_string(current_groups, 0, "custom"),
2074
            ""
2075
          )
2076
        end
2077
      end
2078
      UI.ReplaceWidget(
×
2079
        Id(:rpfilter),
2080
        HBox(
2081
          # label, e.g. 'Filter: Local Users', 'Filter: Custom'
2082
          Left(
2083
            Label(Id(:current_filter), Builtins.sformat(_("Filter: %1"), curr))
2084
          ),
2085
          # MenuButton label
2086
          MenuButton(
2087
            Id(:sets),
2088
            Opt(:key_F2),
2089
            _("&Set Filter"),
2090
            GetSetsItems(current_summary)
2091
          )
2092
        )
2093
      )
2094

2095
      nil
2096
    end
2097
    def HandleFilterLine(widget_id, event)
1✔
2098
      event = deep_copy(event)
×
2099
      ev_id = Ops.get(event, "ID")
×
2100
      current_summary = UsersCache.GetCurrentSummary
×
2101

2102
      if current_summary == "users" && Ops.is_string?(ev_id) &&
×
2103
          Builtins.contains(
2104
            Users.GetAvailableUserSets,
2105
            Convert.to_string(ev_id)
2106
          )
2107
        if ev_id == "ldap" && Ldap.bind_pass == nil
×
2108
          Ldap.SetBindPassword(Ldap.GetLDAPPassword(true))
×
2109
          return nil if Ldap.bind_pass == nil
×
2110
        end
2111
        popup = false
×
2112
        if ev_id == "ldap" && Users.LDAPNotRead ||
×
2113
            ev_id == "nis" && Users.NISNotRead
2114
          UI.OpenDialog(
×
2115
            Opt(:decorated),
2116
            # wait popup
2117
            Label(_("Reading sets of users and groups. Please wait..."))
2118
          )
2119
          popup = true
×
2120
        end
2121
        if Users.ChangeCurrentUsers(Convert.to_string(ev_id))
×
2122
          if popup
×
2123
            UI.CloseDialog
×
2124
            popup = false
×
2125
          end
2126
          UsersCache.SetCustomizedUsersView(ev_id == "custom")
×
2127
          SummaryTableInit("table")
×
2128
          InitFilterLine(widget_id)
×
2129
          InitTabUsersGroups("")
×
2130
        end
2131
        UI.CloseDialog if popup
×
2132
        return nil
×
2133
      end
2134
      if current_summary == "groups" && Ops.is_string?(ev_id) &&
×
2135
          Builtins.contains(
2136
            Users.GetAvailableGroupSets,
2137
            Convert.to_string(ev_id)
2138
          )
2139
        if ev_id == "ldap" && Ldap.bind_pass == nil
×
2140
          Ldap.SetBindPassword(Ldap.GetLDAPPassword(true))
×
2141
        end
2142
        popup = false
×
2143
        if ev_id == "ldap" && Users.LDAPNotRead ||
×
2144
            ev_id == "nis" && Users.NISNotRead
2145
          UI.OpenDialog(
×
2146
            Opt(:decorated),
2147
            # wait popup
2148
            Label(_("Reading sets of users and groups. Please wait..."))
2149
          )
2150
          popup = true
×
2151
        end
2152
        if Users.ChangeCurrentGroups(Convert.to_string(ev_id))
×
2153
          if popup
×
2154
            UI.CloseDialog
×
2155
            popup = false
×
2156
          end
2157
          UsersCache.SetCustomizedGroupsView(ev_id == "custom")
×
2158
          SummaryTableInit("table")
×
2159
          InitFilterLine(widget_id)
×
2160
          InitTabUsersGroups("")
×
2161
        end
2162
        UI.CloseDialog if popup
×
2163
        return nil
×
2164
      end
2165
      if ev_id == :customize
×
2166
        if CustomizePopup(current_summary) && UsersCache.CustomizedUsersView
×
2167
          SummaryTableInit("table")
×
2168
        end
2169
        InitFilterLine(widget_id)
×
2170
        InitTabUsersGroups("")
×
2171
        return nil
×
2172
      end
2173
      if !Ops.is_symbol?(ev_id)
×
2174
        Builtins.y2error("strange ev_id value: %1", ev_id)
×
2175
        return nil
×
2176
      end
2177
      Convert.to_symbol(ev_id)
×
2178
    end
2179

2180

2181

2182
    # helper function to get information about authentication from
2183
    # appropriate module
2184
    # @param [String] client
2185
    # @return
2186
    def get_module_data(client)
1✔
2187
      ret = ""
×
2188
      progress_orig = Progress.set(false)
×
2189
      if !Builtins.contains(@installed_clients, client)
×
2190
        ret = Summary.NotConfigured
×
2191
      elsif client == "sssd"
×
2192
        begin
2193
          require 'auth/authconf.rb'
×
2194
        rescue LoadError
2195
          ret = _("<b>yast2-auth-client module not installed</b>")
×
2196
        else
2197
          ::Auth::AuthConfInst.read_all
×
2198
          ret = ::Auth::AuthConfInst.summary_text
×
2199
        end
2200
      elsif client == "nis"
×
2201
        WFM.CallFunction("nis_auto", ["Read"])
×
2202
        a = WFM.CallFunction("nis_auto", ["ShortSummary"])
×
2203
        ret = Convert.to_string(a) if Ops.is_string?(a)
×
2204
      elsif client == "samba"
×
2205
        WFM.CallFunction("samba-client_auto", ["Read"])
×
2206
        a = WFM.CallFunction("samba-client_auto", ["ShortSummary"])
×
2207
        ret = Convert.to_string(a) if Ops.is_string?(a)
×
2208
      end
2209
      Progress.set(progress_orig)
×
2210
      ret
×
2211
    end
2212

2213
    # Reloads the configuration for given client and creates updated
2214
    # summary widget contents
2215
    # returns the summary value for richtext
2216
    def reload_config(clients)
1✔
2217
      clients = deep_copy(clients)
×
2218
      summary = ""
×
2219
      if clients == nil || clients == []
×
2220
        clients = deep_copy(@configurable_clients)
×
2221
      end
2222
      Builtins.foreach(clients) do |client|
×
2223
        summary = Summary.AddHeader(
×
2224
          summary,
2225
          Builtins.sformat(
2226
            "<font color=\"#8BC460\"><a href=\"%1\">%2</a></font>",
2227
            client,
2228
            Ops.get_string(@client_label, client, client)
2229
          )
2230
        )
2231
        summary = Summary.AddLine(summary, get_module_data(client))
×
2232
      end
2233
      summary
×
2234
    end
2235

2236

2237
    # Init the widgets in Authentication tab
2238
    def InitAuthData(key)
1✔
2239
      mb = []
×
2240

2241
      # check availability of authentication packages,
2242
      # update the RichText summary and menubutton labels accordingly
2243
      Builtins.foreach(@configurable_clients) do |client|
×
2244
        package = @auth_methods[client]["package"] or raise "Unknown auth client #{client}"
×
2245

2246
        client_item = Item(
×
2247
          Id(client),
2248
          @auth_methods[client]["label"]
2249
        )
2250

2251
        if Package.Installed(package)
×
2252
          @installed_clients = Builtins.add(@installed_clients, client)
×
2253
        end
2254

2255
        mb << client_item
×
2256

2257
        UI.ChangeWidget(
×
2258
          Id("auth_summary"),
2259
          :Value,
2260
          Ops.add(
2261
            Convert.to_string(UI.QueryWidget(Id("auth_summary"), :Value)),
2262
            reload_config([client])
2263
          )
2264
        )
2265
      end
2266

2267
      if ! mb.empty?
×
2268
        UI.ReplaceWidget(
×
2269
          Id(:rpbutton),
2270
          # menu button label
2271
          MenuButton(Opt(:key_F4), _("&Configure..."), mb)
2272
        )
2273
      end
2274

2275
      nil
2276
    end
2277

2278

2279
    # Handler for actions in Authentication tab
2280
    def HandleAuthData(key, event)
1✔
2281
      event = deep_copy(event)
×
2282
      return nil if Ops.get_string(event, "EventType", "") != "MenuEvent"
×
2283
      button = Ops.get_string(event, "ID", "")
×
2284

2285
      return nil if !Builtins.contains(@configurable_clients, button)
×
2286

2287
      if !Builtins.contains(@installed_clients, button)
×
2288
        package = @auth_methods[button]["package"]
×
2289
        if @check_available
×
2290
          avai = Package.Available(package)
×
2291
          if avai == nil
×
2292
            # package manager is probably not accessible -> no more checks
2293
            @check_available = false
×
2294
          end
2295
          if avai != true
×
2296
            # error popup, %1 is package name
2297
            Popup.Error(
×
2298
              Builtins.sformat(
2299
                _("Package %1 is not available for installation."),
2300
                package
2301
              )
2302
            )
2303
            @configurable_clients = Builtins.filter(@configurable_clients) do |p|
×
2304
              p != button
×
2305
            end
2306
            UI.ChangeWidget(Id("auth_summary"), :Value, reload_config([]))
×
2307
            return nil
×
2308
          end
2309
        end
2310
        if Package.InstallAllMsg(
×
2311
            [package],
2312
            # popup label (%1 is package to install)
2313
            Builtins.sformat(
2314
              _("Package %1 is not installed.\nInstall it now?\n"),
2315
              package
2316
            )
2317
          )
2318
          @installed_clients = Builtins.add(@installed_clients, button)
×
2319
        else
2320
          return nil
×
2321
        end
2322
      end
2323
      param = installation ? ["from_users"] : []
×
2324
      if WFM.CallFunction(@auth_methods[button]["call"], param) == :next
×
2325
        UI.ChangeWidget(Id("auth_summary"), :Value, reload_config([]))
×
2326
      end
2327
      nil
2328
    end
2329

2330
    # Actions done when Authentication tab is left
2331
    def StoreAuthData(key, event)
1✔
2332
      event = deep_copy(event)
×
2333
      was_nis_available = Users.NISAvailable
×
2334
      was_ldap_available = Users.LDAPAvailable
×
2335
      Users.ReadSourcesSettings
×
2336

2337
      # enabling NIS/LDAP could add + lines (they are not in current cache that
2338
      # would be saved after user modifications):
2339
      if !was_nis_available && Users.NISAvailable ||
×
2340
          !was_ldap_available && Users.LDAPAvailable
2341
        Builtins.y2milestone("ldap or nis enabled now")
×
2342
        Users.AddPlusPasswd("+::::::")
×
2343
        Users.AddPlusGroup("+:::")
×
2344
        Users.AddPlusShadow("+")
×
2345
      end
2346

2347
      nil
2348
    end
2349
  end
2350
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc