Added client work scripts
[clearscm.git] / clients / Ameriquest / triggers / Permissions.pl
1 #!/usr/bin/perl
2 ################################################################################
3 #
4 # File:         Permissions.pl
5 # Description:  This trigger script implements additional permissions checking.
6 #               The general idea is to open up permissions at the group level
7 #               and to control who gets to checkout elements at the folder
8 #               level. You do this by making an element named
9 #               $permissions_element which contains group names of which
10 #               groups have "checkout" permissions in that folder downward.
11 # Author:       Andrew@DeFaria.com
12 # Created:      Mon Jul 19 10:54:01 PDT 2004
13 # Language:     Perl
14 # Modifications:
15 #
16 # (c) Copyright 2004, Andrew@DeFaria.com, all rights reserved
17 #
18 ################################################################################
19 use strict;
20 use warnings;
21 use File::Spec;
22
23 # This will be set in the BEGIN block but by putting them here the become
24 # available for the whole script.
25 my (
26   $abs_path,
27   $lib_path,
28   $log_path,
29   $me,
30   $triggers_path
31 );
32
33 BEGIN {
34   # Extract relative path and basename from script name.
35   $0 =~ /(.*)[\/\\](.*)/;
36
37   $abs_path     = (!defined $1) ? "." : File::Spec->rel2abs ($1);
38   $me           = (!defined $2) ? $0  : $2;
39
40   # Setup paths
41   $lib_path             = "$abs_path/../lib";
42   $log_path             = "$abs_path/../log";
43   $triggers_path        = "$abs_path/../triggers";
44
45   # Add the appropriate path to our modules to @INC array.
46   unshift (@INC, "$lib_path");
47 } # BEGIN
48
49 use TriggerUtils;
50
51 # Name of permissions element to search for
52 my $permissions_element = ".perms";
53
54 # Trigger environment variables used
55 my $pname = $ENV{CLEARCASE_PN};
56 my $user  = $ENV{CLEARCASE_USER};
57 my $vob   = $ENV{CLEARCASE_VOB_PN};
58
59 sub ParentDir {
60   my $path = shift;
61
62   $path =~ m/(.*)[\/\\].*/;
63
64   return $1;
65 } # ParentDir
66
67 # Returns the current group owner of the vob. This is the first group listed, not the'
68 # "Additional groups".
69 sub GetGroupOwner {
70   my $vob = shift;
71
72   my @output = `cleartool describe vob:$vob 2>&1`;
73
74   foreach (@output) {
75     chomp; chop if /\r/;
76     if (/group AMERIQUEST\\(.*)/) {
77       return $1;
78     } # if
79   } # foreach
80
81   return "Unknown";
82 } # GetGroupOwner
83
84 # Returns the primary group using creds
85 sub GetPrimaryGroup {
86   my @output = `"C:\\Program Files\\Rational\\Clearcase\\etc\\utils\\creds.exe" 2>&1`;
87
88   foreach (@output) {
89     chomp; chop if /\r/;
90     if (/Primary group: AMERIQUEST\\(\S*).*/) {
91       return $1;
92     } # if
93   } # foreach
94
95   return "Domain Users";
96 } # GetPrimaryGroup
97
98 # Parsed the $permissions_element returning a list of permitted groups.
99 sub Parse {
100   my $permissions_element = shift;
101
102   open PERMISSIONS_ELEMENT, $permissions_element
103     or clearlogmsg "Unable to open $permissions_element - $!\n", exit 1;
104
105   my @lines = <PERMISSIONS_ELEMENT>;
106   my @tidy_lines;
107
108   foreach (@lines) {
109     chomp; chop if /\r/;
110     next if $_ eq "";
111     push @tidy_lines, $_;
112   } # foreach
113
114   return @tidy_lines;
115 } # Parse
116
117 # Compare the two string arrays and return 1 if there are any matches.
118 sub IsAMember {
119   my $set1      = shift;
120   my $set2      = shift;
121
122   # Convert two array references to actual arrays
123   my @set1      = @{$set1};
124   my @set2      = @{$set2};
125
126   foreach my $item1 (@set1) {
127     foreach my $item2 (@set2) {
128       return 1 if $item1 eq $item2;
129     } # foreach
130   } # foreach
131
132   return 0;
133 } # IsAMember
134
135 # Returns an array of (AMERIQUEST) group names for the user using creds.
136 sub GetUserGroups {
137   my @output = `"C:\\Program Files\\Rational\\Clearcase\\etc\\utils\\creds.exe" 2>&1`;
138   my @groups;
139   my $found = 0;
140
141   foreach (@output) {
142     chomp; chop if /\r/;
143
144     # We should first see the Primary Grou
145     if (/Primary group: AMERIQUEST\\(.*) \(/) {
146       push @groups, $1;
147     } # if
148
149     # When we hit the "Groups:" line then what follows is a list of groups
150     if (/^Groups:/) {
151       $found = 1;
152       next
153     } # if
154
155     # Select only those that are specifically in the AMERIQUEST domain
156     if ($found eq 1 and /\s*AMERIQUEST\\(.*) \(/) {
157       push @groups, $1;
158     } # if
159   } # foreach
160
161   return @groups
162 } # GetUserGroups
163
164 # This routine will check to see if any of the user's groups are in the
165 # $permissions_element(s) by recursing up the directory looking for 
166 # $permissions_element(s) then comparing those groups to the user's groups.
167 sub Permitted {
168   my $vob               = shift;
169   my $pname             = shift;
170   my @user_groups       = @_;
171
172   # User may be attemptign to Add to Source Control in the current
173   # directory and have permissions to do so. When Add to Source
174   # Control runs it checks out the parent directory. The user
175   # typically will NOT have permissions to check out the parent
176   # directory! So for directory elements first check if the user is
177   # permitted as per $pname/$permissions_element BEFORE traversing up
178   # to the parent directory.
179   my @permitted_groups;
180   my $element_type = $ENV{CLEARCASE_ELTYPE};
181
182   if ($element_type =~ /directory/i) {
183     if (-e "$pname/$permissions_element") {
184       @permitted_groups = Parse ("$pname/$permissions_element");
185       return 1 if (IsAMember (\@user_groups, \@permitted_groups));
186     } # if
187   } # if
188         
189   # Get parent directory
190   $pname = ParentDir $pname;
191
192   # Exhausted $pname
193   return 0 if !defined $pname;
194
195   if (-e "$pname/$permissions_element") {
196     @permitted_groups = Parse ("$pname/$permissions_element");
197     return 1 if (IsAMember (\@user_groups, \@permitted_groups));
198   } # if
199
200   # Recurse up to parent directory
201   return Permitted ($vob, $pname, @user_groups);
202 } # Permitted
203
204 # Main
205 my $vob_group_owner     = GetGroupOwner $vob;
206 my $group               = GetPrimaryGroup;
207 my @user_groups         = GetUserGroups;
208 my $msg;
209
210 if ($vob_group_owner eq $group) {
211   # Vob group openers are always permitted
212   exit 0;
213 } elsif ($pname =~ m/$permissions_element$/) {
214   # User trying to check out the $permissions_element!
215   $msg .= "Only members of the vob's initial group owners,\\n";
216   $msg .= "$vob_group_owner, may checkout the $permissions_element element!";
217   clearmsg $msg;
218   exit 1;
219 } elsif (Permitted ($vob, $pname, @user_groups)) {
220   exit 0;
221 } else {
222   $msg .= "The userid of $user is not a member of a group who is\\n";
223   $msg .= "permitted to check out elements from the folder\\n";
224   $msg .= ParentDir $pname;
225   $msg .= " of the $vob vob.";
226   clearmsg $msg;
227   exit 1;
228 } # if