summaryrefslogtreecommitdiff
path: root/rt/docs/design_docs
diff options
context:
space:
mode:
Diffstat (limited to 'rt/docs/design_docs')
-rw-r--r--rt/docs/design_docs/acls228
-rw-r--r--rt/docs/design_docs/approval_notices8
-rw-r--r--rt/docs/design_docs/approval_template25
-rw-r--r--rt/docs/design_docs/cf_search72
-rw-r--r--rt/docs/design_docs/cli_spec361
-rw-r--r--rt/docs/design_docs/delegation115
-rw-r--r--rt/docs/design_docs/evil_plans9
-rw-r--r--rt/docs/design_docs/groups_notes88
-rw-r--r--rt/docs/design_docs/recursive_group_membership_algorithm109
-rw-r--r--rt/docs/design_docs/rql_parser_machine.graphviz32
-rw-r--r--rt/docs/design_docs/string-extraction-guide.txt100
-rw-r--r--rt/docs/design_docs/ticket_templates16
12 files changed, 622 insertions, 541 deletions
diff --git a/rt/docs/design_docs/acls b/rt/docs/design_docs/acls
index 3b9d856..bb093ad 100644
--- a/rt/docs/design_docs/acls
+++ b/rt/docs/design_docs/acls
@@ -1,206 +1,50 @@
-$Header: /home/cvs/cvsroot/freeside/rt/docs/design_docs/acls,v 1.1 2002-08-12 06:17:07 ivan Exp $
+Does principal baz have right foo for object bar
-# {{{ Requirements
+What rights does user baz have for object bar
-Here's the rough scheme I was thinking of for RT2 acls. Thoughts? I think
-it's a lot more flexible than RT 1.0, but not so crazily complex that
-it will be impossible to implement. One of the "interesting" features
-is the ability to grant acls based on watcher status. This now lives
-in design-docs/acls
+# {{{ Which principals have right foo for object bar
- jesse
-Who can rights be granted to:
+if ($args{'ObjectType'} eq 'Ticket') {
+ $or_check_ticket_roles = " OR ( Groups.Domain = 'TicketRole' AND Groups.Instance = '".$args{'ObjectId'}."') ";
+ # If we're looking at ticket rights, we also want to look at the associated queue rights.
+ # this is a little bit hacky, but basically, now that we've done the ticket roles magic, we load the queue object
+ # and ask all the rest of our questions about the queue.
+ my $tick = RT::Ticket->new($RT::SystemUser);
+ $tick->Load($args{'ObjectId'});
+ $args{'ObjectType'} = 'Queue';
+ $args{'ObjectId'} = $tick->QueueObj->Id();
- users whose id is <foo>
- users who are watchers of type <requestor/cc/admincc> for <queue/ticket> <id>
- users who are watchers of type <requestor/cc/admincc> for <this ticket / this queue>
-
-
-what scope do these rights apply to
- queue <id>
- system
-
-
-What rights can be granted
- Display Ticket
- Manipulate Ticket
- Only users with manipulate ticket level access will see comments
- Maniplulate Ticket Status
- Create Ticket
-
- Admin Queue Watchers
- Admin Ticket Watchers
- Admin user accounts
- Admin scrips
- Admin scripscopes
- Admin Queue ACLS
- Admin System ACLs
-
-# }}}
-
-
-# {{{ Prinicpals These are the entities in your Access Control Element
-#
-
-Principal: What user does this right apply to
-
- Made up of:
- PrincipalScope, PrincipalType and PrincipalId
-
-
- User:
- Scope: User
- Type: null
- Id: A userid or 0
-
- Owner:
- Scope: Owner
- Type: null
- Id: none
-
-
- Watchers:
-
- Scope: Ticket
- Type: Requestors; Cc; AdminCc
- Id: A ticket id or 0 for "this ticket"
-
- Scope: Queue
- Type: Cc; AdminCc
- Id: A queue id or 0 for "this queue"
-
-
-# }}}
-
-# {{{ Object: What object does this right apply to
-
- Object is composed of an ObjectType and an ObjectId
-
- Type: System
- Id: NULL
-
- Type: Queue
- Id: Integer ref to queue id or 0 for all queues
-
-# }}}
-
-# {{{ Right: (What does this entry give the principal the right to do)
-
-
-
- For the Object System:
- System::SetACL
- System::AdminScrips
-
- User::Display
- User::Create
- User::Destroy
- User::Modify
- User::SetPassword
-
-
-
- For the Object "Queue":
- Queue::Admin
- Queue::SetACL
- Queue::Create
- Queue::Display
- Queue::Destroy
- Queue::ModifyWatchers
- Ticket::Create
- Ticket::Destory
- Ticket::Display
- Ticket::Update
- Ticket::UpdateRequestors
- Ticket::UpdateCc
- Ticket::UpdateAdminCc
- Ticket::NotifyWatchers
-
-
- DEFERRED
-
- Ticket::SetStatus: (Values)
- Open
- Resolved
- Stalled
- <null> means any
-
-
-# }}}
-
-
-# {{{ Implementation:
-
-# {{{ SQL Schema
-CREATE TABLE ACL (
- id int not null primary_key autoincrement,
- PrinicpalId INT(11),
- PrincipalType VARCHAR(16),
- PrincipalScope VARCHAR(16),
- ObjectType VARCHAR(16),
- ObjectId INT,
- Right VARCHAR(16)
-);
-
-# }}}
-
-# {{{ perl implementation of rights searches
-
-sub Principals {
-if (defined $Ticket) {
- return "($UserPrincipal) OR ($OwnerPrincipal) OR ($WatchersPrincipal)";
- }
-else {
- return "($UserPrincipal) OR ($WatchersPrincipal)";
- }
}
-
-$Principals = " ($UserPrincipal) OR ($OwnerPrincipal) OR ($WatchersPrincipal)";
-
-$UserPrincipal = " ( ACE.PrincipalScope = 'User') AND
- ( ACE.PrincipalId = $User OR ACE.PrincipalId = 0)";
-
-$OwnerPrincipal = " ( ACE.PrinciaplScope = 'Owner') AND
- ( Tickets.Owner = "$User ) AND
- ( Tickets.Id = $Ticket)";
-
-$WatchersPrincipal = " ( ACE.PrincipalScope = Watchers.Scope ) AND
- ( ACE.PrincipalType = Watchers.Type ) AND
- ( ACL.PrincipalId = Watchers.Value ) AND
- ( Watchers.Owner = $User )";
-
-$QueueObject = "( ACE.ObjectType = 'Queue' and (ACE.ObjectId = $Queue OR ACE.ObjectId = 0)";
-
-$SystemObject = "( ACE.ObjectType = 'System' )";
-
-
-# This select statement would figure out if A user has $Right at the queue level
-
-SELECT ACE.id from ACE, Watchers, Tickets WHERE (
- $QueueObject
- AND ( ACE.Right = $Right)
- AND ($Principals))
+if ($args{'ObjectType'} eq 'Queue') {
+ $or_check_roles = " OR ( ( (Groups.Domain = 'QueueRole' AND Groups.Instance = '".$args{'ObjectId'}."') $or_check_ticket_roles )
+ AND Groups.Type = ACL.PrincipalType AND Groups.Id = Principals.ObjectId AND Principals.PrincipalType = 'Group') ";
+}
-# This select statement would figure outif a user has $Right for the "System"
+if (defined $args{'ObjectType'} ) {
+ $or_look_at_object_rights = " OR (ACL.ObjectType = '".$args{'ObjectType'}."' AND ACL.ObjectId = '".$args{'ObjectId'}."') ";
-SELECT ACE.id from ACE, Watchers, Tickets WHERE (
- ($SystemObject) AND ( ACE.Right = $Right ) AND ($Principals))
+}
-# }}}
+my $query = "SELECT Users.* from ACL, Groups, Users, Principals, Principals UserPrinc, CachedGroupMembers WHERE
+ Users.id = UserPrinc.ObjectId AND UserPrinc.PrincipalType = 'User' AND
+ Principals.Id = CachedGroupMembers.GroupId AND
+ CachedGroupMembers.MemberId = UserPrinc.ObjectId AND
+ UserPrinc.PrincipalType = 'User' AND
+ (ACL.RightName = 'SuperUser' OR ACL.RightName = '$right') AND
+ (ACL.ObjectType = 'System' $or_look_at_object_rights) AND
+ (
+ (ACL.PrincipalId = Principals.Id AND
+ Principals.ObjectId = Groups.Id AND
+ ACL.PrincipalType = 'Group' AND
+ (Groups.Domain = 'SystemInternal' OR Groups.Domain = 'UserDefined' OR Groups.Domain = 'ACLEquivalence')
+ )
+ $or_check_roles
+ )";
# }}}
-# {{{ Examples
-#
-
-# }}}
-
-
-
-Unaddressed issues:
-
- There needs to be a more refined method for grouping users, such that members of the customer service department
-can't change sysadmins' passwords.
+What objects does principal baz have right foo for
+;
diff --git a/rt/docs/design_docs/approval_notices b/rt/docs/design_docs/approval_notices
new file mode 100644
index 0000000..5e76119
--- /dev/null
+++ b/rt/docs/design_docs/approval_notices
@@ -0,0 +1,8 @@
+Notification on "your request approved by"
+Notification on "your request approved by all approvers"
+Notification on "your request denied by"
+Reject ticket on rejection of any approval
+
+"Ticket N is pending your approval"
+
+
diff --git a/rt/docs/design_docs/approval_template b/rt/docs/design_docs/approval_template
new file mode 100644
index 0000000..16a988c
--- /dev/null
+++ b/rt/docs/design_docs/approval_template
@@ -0,0 +1,25 @@
+===Create-Ticket: approval
+ { my $name = "HR";
+ my $groups = RT::Groups->new($RT::SystemUser);
+ $groups->LimitToUserDefinedGroups();
+ $groups->Limit(FIELD => 'Name', OPERATOR => '=', VALUE => "$name");
+ $groups->WithMember($TransactionObj->CreatorObj->Id);
+
+ my $groupid = $groups->First->Id;
+
+ my $adminccs = RT::Users->new($RT::SystemUser);
+ $adminccs->WhoHaveRight(Right => 'AdminGroup', IncludeSystemRights => undef, IncludeSuperusers => 0, IncludeSubgroupMembers => 0, Object => $groups->First);
+
+ my @admins;
+ while (my $admin = $adminccs->Next) {
+ push (@admins, $admin->Name);
+ }
+ }
+ Queue: Approvals
+ Type: Approval
+ AdminCcs: {join (", ",@admins) }
+ Depended-On-By: {$tickets{'TOP'}->Id}
+ Refers-To: {$tickets{'TOP'}->Id}
+ Due: {time + 86400}
+ Content-Type: text/plain
+ Content: Your approval is requested for the ticket {%$tickets{'TOP'}->Id}: {$tickets{'TOP'}->Subject}
diff --git a/rt/docs/design_docs/cf_search b/rt/docs/design_docs/cf_search
new file mode 100644
index 0000000..456a9fe
--- /dev/null
+++ b/rt/docs/design_docs/cf_search
@@ -0,0 +1,72 @@
+find all tickets where:
+
+
+ CF Foo
+ Has values (talk or read) AND
+ Has values (bar and baz) AND
+ doesn't have values (bing or bong)
+
+
+LimitCustomFieldValues {
+ my %args = ( CustomField => undef,
+ ClauseId => 'CustomFields',
+ OPERATOR => undef,
+ ENTRYAGGREGATOR => undef,
+ VALUES => undef,
+ @_) ;
+
+ unless ( $self->{'TicketAliases'}{$args{'ClauseId'}}{'CustomField'} ) {
+ $self->{'TicketAliases'}{$args{'ClauseId'}}{'CustomField'} = $self->NewAlias('CustomFields');
+ $self->Join(TABLE1 =>$self->{'TicketAliases'}{$args{'ClauseId'}}{'CustomField' },
+ FIELD1 => 'QueueId',
+ TABLE2 => 'main', FIELD2 => 'QueueId');
+
+ if ($args{'OPERATOR'} =~ /!=|IS/i) {
+ }
+ else {
+ }
+
+}
+ # {{{ if it's a keyword
+ elsif ( $TYPES{ $restriction->{'FIELD'} } eq 'CUSTOMFIELD' ) {
+
+ my $null_columns_ok;
+ my $TicketCFs = $self->Join( TYPE => 'left',
+ ALIAS1 => 'main',
+ FIELD1 => 'id',
+ TABLE2 => 'TicketCustomFieldValues',
+ FIELD2 => 'Ticket' );
+
+ foreach my $value ( @{ $restriction->{'VALUES'} } ) {
+ $self->SUPER::Limit( ALIAS => $TicketCFs,
+ FIELD => 'Content',
+ OPERATOR => $restriction->{'OPERATOR'},
+ VALUE => $value,
+ QUOTEVALUE => $restriction->{'QUOTEVALUE'},
+ ENTRYAGGREGATOR => 'AND', );
+ }
+ if ( ( $restriction->{'OPERATOR'} =~ /^IS$/i ) or ( $restriction->{'OPERATOR'} eq '!=' ) ) {
+ $null_columns_ok = 1;
+ }
+
+ #If we're trying to find tickets where the keyword isn't somethng, also check ones where it _IS_ null
+ if ( $restriction->{'OPERATOR'} eq '!=' ) {
+ $self->SUPER::Limit( ALIAS => $TicketCFs,
+ FIELD => 'Content',
+ OPERATOR => 'IS',
+ VALUE => 'NULL',
+ QUOTEVALUE => 0,
+ ENTRYAGGREGATOR => 'OR', );
+ }
+
+ $self->SUPER::Limit( LEFTJOIN => $TicketCFs,
+ FIELD => 'CustomField',
+ VALUE => $restriction->{'CUSTOMFIELD'},
+ ENTRYAGGREGATOR => 'OR' );
+
+ }
+
+ # }}}
+
+ }
+
diff --git a/rt/docs/design_docs/cli_spec b/rt/docs/design_docs/cli_spec
index 48a7f34..ae5f29f 100644
--- a/rt/docs/design_docs/cli_spec
+++ b/rt/docs/design_docs/cli_spec
@@ -1,354 +1,31 @@
-Find tickets to operate on:
- --id=<tickets> Find only tickets in the range <tickets>
- synonyms:
- --limit-id, --tickets, --limit-tickets
- --limit-queue=<queue>
- --limit-status=<status>
- --limit-owner=<owner>
- --limit-priority=<priority>
- --limit-requestor=<email>
- --limit-subject=<string> (Subject contains)
- --limit-body=<string> (body contains)
- --limit-created=(before/after) <date>
- --limit-due=(before/after) <date>
- --limit-starts=(before/after) <date>
- --limit-started=(before/after) <date>
+Things the cli must do
+ create ticket
+ comment
+ reply
+ update ticket metadata
+ search for tickets
+ update a bunch of tickets.
+ list tickets
+ login/logout
- --limit-first=<int> Start on the <int>th row returned by the
- database
- --limit-rows=<int> Find only <int> rows
-Display:
- --show shows a ticket history
- --history ditto
+should support multiple rt servers
- --summary default option. shows a ticket summary
- --format Optional format string. If not specified,
- uses the value of ENV{'RT_LISTING_FORMAT'}
- or an internal default
-
+create/edit/update should use EDITOR or take from a file or stdin
-Basic ticket editing:
+should be able to update ticket sttributes from a commandline without invoking an editor or needing to use stdin.
- --status=(open|stall|resolve|kill)
- --subject=<string>
- --owner=<owner>
- --queue=<queue>
- --time-left=<minutes>
+login/logout should store RT session cookies rather than constantly transmitting the username/password combo.
-Watcher-related editing:
+rtserver and rt username should come from env variables. but should be able to be overridden by commandline options.
- --add-requestor=<email>
- --del-requestor=<email>
- --add-cc=<email>
- --del-cc=<email>
- --add-admincc=<email>
- --del-admincc=<email>
+rt password should be able to be specified on the commandline (say from a script) or, failing that be prompted for within the application (as rt's sbin/initdb script does) ...or maybe able to be read from a stash file on disk.
-Priority related editing:
+must be able to dowaload attachments from cli.
+
+ it might also be cool to be able to generate session-length urls for attavhments so you can use a browser. but that's not necessary.
- --priority=<int>
- --final-priority=<int>
-Date related editing:
-
- --due=date
- --starts=date
- --started=date
- --contacted=date
-
-
-
-Ticket updates:
-
- --comment
- --reply | --respond
-
-
-Links
-
- --add-link
- --type=<DependsOn|MemberOf|RelatedTo>
- needs one of:
- --target=<ticketid>
- --base=<ticketid>
-
- --del-link <link-id>
-
-
-
-Condiments:
- any update can take:
-
- --time-taken <minutes>
-
- Ticket updates can take:
-
- --source -- specify a source file to read the content from
- --edit = give me an editor to edit the message
- --no-edit = don't give me an editor to edit the message.
-
-
-
-
------ Forwarded message from deborah kaplan <deborah@curl.com> -----
-
-Date: Fri, 14 Apr 2000 11:43:18 -0400 (EDT)
-From: deborah kaplan <deborah@curl.com>
-To: Jesse <jesse@fsck.com>
-Subject: Re: [rt-devel] RT Projects list
-
-Finally, here is the functional spec for the command line
-interface. This is for the user interface only; if you think
-this is right, I will add the administrative interface as well.
-Should I post to rt-devel, add to the ticket, or just modify
-based on your kibbitzing? When you are happy with it I'll start
-the code.
-
--deborah
-
-
-RT command line interface functional specification
-Author: Deborah Kaplan (Deborah@suberic.net)
-Version:0.1
-
-Requirements:
-
-RT needs a CLI for various reasons. If a user is restricted to a
-dumb terminal, she needs to be able to access the RT database and
-manipulate it fully. The full functionality of both the RT
-database and the RT administrative interface should be available
-from this CLI.
-
-There are two possible types of CLI which I will discuss here.
-The first is a curses-style interface, which allows the user to
-move about a series of menus and choices, usually using arrow
-keys. As RT supplies a Web interface, there is no need for this
-curses-style interface to be written as part of RT. Instead, the
-RT developers should pick one tty-based Web browser (e.g. lynx,
-w3m) and make sure that all of the RT pages are easily readable
-with that tty based browser. Installation of that browser should
-be recommended in the RT installation documentation as a
-supported method of accessing RT from a tty.
-
-The second possible type of CLI is more minimal: a series of
-commands which can be run at a UNIX command prompt which provide
-full functionality to the RT database and administrative
-interface. There are two major benefits to this second type of
-CLI. First of all, in order to use this CLI, you need no extra
-tools (Web browsers, etc.). All that is required is a UNIX
-command line prompt and an installation of RT. Secondly, a user
-of RT who has a very specific command to run and who knows the
-appropriate CLI commands can accomplish her task much more
-quickly with a single command then she could navigating through a
-menu based interface.
-
-In the specification, I will describe the second type of CLI.
-
-Caveats:
-
-This specification draws heavily on the structure of formatting
-command line options for cvs. RT faces a smaller version of the
-same kinds of problems cvs faces: we want to create a very rich
-command set without sacrificing ease-of-use.
-
-I am not wedded to any specific command names if they seem
-impractical; I merely am proposing the command names that seem
-reasonable to me at this moment.
-
-Finally, I am finding the functioning of the web UI from RT 1.
-If the functionality differs greatly in RT 2, I will need to
-modify this specification.
-
-Specification:
-
-There are two commands: "rt", which is the primary interface to
-the database, and "rtadmin", which is the administrative
-interface to the database.
-
-The format of an rt command is as follows:
-
- rt <command>
- <command> is one of:
-
- - help
- print an overview of the commands which can be run
-
- - print <queue> <options>
- with no options, dump to the screen a list of all open
- requests in <queue> -- the equivalent of "Display Queue" in
- the existing Web interface.
-
- <queue> is the name of an RT queue
- <option> is either:
-
- -f <filename> | --filename <filename>
- where <filename> is the name of a file (defaulting to
- ~/.rtrc) in which the options described below can be
- placed in the format "^ <long option name> <option value>
- $".
-
- Or a series of the following options:
-
- -o <owner name> | --owner <owner name>: restrict tickets
- viewed to those owned by <owner name>.
- This option can be used multiple times in one call of
- the rt command in order to produce a list which
- contains tickets owned by multiple owners. Giving the
- empty string ("") as an option to this switch will
- restrict tickets viewed to those which have no owner.
- If this switch is given with no argument, the option
- defaults to the user name of the currently running
- process.
-
- -r <requestor name> | --requestor <requestor name>:
- restrict tickets viewed to those requested by <requestor
- name>.
- This option can be used multiple times in one call of
- the rt command in order to produce a list which
- contains tickets requested by multiple requesters. If
- this switch is given with no arguments, it produces an
- error.
-
- -s <status> | --status <status>: restrict tickets viewed
- to those with the status named in <status>.
- This option can be used multiple times in one call of
- the rt command in order to produce a list which
- contains tickets with multiple statuses (statii?
- Dragon NaturallySpeaking recognizes "statuses" as a
- word). This option defaults to status "open".
-
- -j <subject> | --subject <subject>: restrict tickets
- viewed to those which contain <subject> as a substring in
- the subject field of the ticket.
- This command can be used multiple times in one call of
- the rt command in order to produce a list which
- contains tickets with various subject substrings. If
- the option is called with no argument, the result is
- an error.
-
- -h | --help: print a usage message.
-
- -n | --number: print out a specific ticket.
- This command can be used multiple times to produce a
- list which contains multiple tickets. If the option
- is called with no argument, the result is an error.
-
- This completes all of the print options which are available
- in the Web interface, except the sort options. I maintain
- that this command is already excessively complex, and that
- adding functionality which can be replicated easily by
- standard UNIX tools is unnecessary added complexity. I
- recommend that the man pages and documentation for this
- option contain an example of a command line run (e.g. of rt |
- awk) which replicates the sorting functionality provided by
- the Web interface.
-
- - edit <ticket> <options>
- with no options, or with no <ticket>, produces the same
- output as the --help option.
- Otherwise, edits the ticket with number <ticket> as
- indicated in the options given. All options listed below
- except for --help and --number can be used in conjunction
- with one another to change many features of the same ticket
- all at once.
-
- -h | --help: print usage message
-
- -s <status> | --status <status>: change the status to the
- status listed in <status>.
- No <status> listed, or 1 listed it does not come from
- a list of approve statuses, produces an error.
-
- -o <owner name> | --owner <owner name>: set to the owner
- of the ticket the owner named.
- Follows whatever convention is finally decided on for
- the requirement to steal a ticket that is owned by
- somebody else. No <owner named> listed has the user
- who is running the rt program take the ticket. If
- that user is not a valid owner, or the 1 listed does
- not come from a list of approve names, produces an
- error.
-
- -r <requestor name> | --requestor <requestor name>: sets
- the requestor to <requestor name>.
- Follows any conventions that the Web UI follows to
- make sure that this is a legal name. If not legal, or
- left blank, produces an error.
-
- -j <subject> | --subject <subject>: sets the subject of
- the ticket to <subject>.
- If the option is called with no argument, the result
- is an error.
-
- -n <number one> <number 2> | --number <number one>
- <number 2>: merges ticket number <number one> into ticket
- <number 2>.
- If both arguments are not provided, the result is an
- error.
-
- -q <queue> | --queue <queue>: set the queue to that
- named.
- If <queue> is not listed, or the 1 listed does not
- come from a list of approve queues, produces an
- error.
-
- -a <area> | --area <area>: set the area of the ticket to
- that named.
- If <area> is not listed, or the 1 listed does not come
- from a list of approve areas, produces an error.
-
- -c <time stamp> | --contact <time stamp>: sets the last
- user contact field, and produces an error if the format
- is invalid.
- If the argument is left blank, sets the last user
- contact field to now.
-
- -p <priority> | --priority <priority>: sets the current
- priority to the 1 listed.
- Produces an error if the argument is left blank.
-
- -f <priority> | --final <priority>: sets the final
- priority to the 1 listed.
- Produces an error if the arguments left blank.
-
- -d <date due> | --datedue <date due>: sets the due date
- to the 1 listed.
- Produces an error if the argument is left blank, or if
- the format is invalid.
-
- - comment <options>
- with no options, this command reads from standard input
- until it sees EOF and appends that to the ticket as a
- comment.
-
- -h | --help: print usage message
-
- -c | --comment: append as a comment. This is the default behavior.
-
- -r | --reply: append as a reply.
-
- -f <filename> | --file <filename>: can be used with
- either the comment or reply options. Instead of reading
- from standard input, read the text of the comment or
- reply from the file <filename>.
-
- - report <options>
- this command is a place holder for reporting functionality
- which does not yet exist. It will probably have the
- default behavior to select reports at the command line or
- choose default reports from a .rtrc file. In a future
- version, it can output graphs in some graphical format.
-
-
-
------ End forwarded message -----
-
---
-jesse reed vincent -- root@eruditorum.org -- jesse@fsck.com
-70EBAC90: 2A07 FC22 7DB4 42C1 9D71 0108 41A3 3FB3 70EB AC90
-
-"If IBM _wanted_ to make clones, we could make them cheaper and faster than
-anyone else!" - An IBM Rep. visiting Vassar College's Comp Sci Department.
+I'm envisioning this as similar to the subversion cli, actually.
diff --git a/rt/docs/design_docs/delegation b/rt/docs/design_docs/delegation
new file mode 100644
index 0000000..0e57059
--- /dev/null
+++ b/rt/docs/design_docs/delegation
@@ -0,0 +1,115 @@
+Group ACLs
+
+ the rights:
+
+
+ CreatePersonalGroup
+ CreateGroup
+
+ AdminGroup
+ * Update group metadata and access control list
+ AdminGroupMembers
+ * Add ad delete members of this group
+ ModifyOwnMembership
+ * Join and quit this group
+
+
+ the primitives:
+
+In user.pm
+
+=item HasRight { Right => 'somerightname', ObjectType => 'Group', ObjectId => 'GroupId'
+
+ Returns true if this user has the right 'somerightname' for
+the group with id 'Id'
+
+=cut
+
+
+=item RightsForObject { ObjectType => 'Group', ObjectId =>'GroupId' }
+
+in users.pm
+
+=item WhoHaveRight { Right =>'somerightname', ObjectType => 'Group', ObjectId => 'GroupId' }
+
+
+ Finds all users who have the right 'somerightname' for the group
+in question.
+
+ If a user has "AdminGroupMembers" globally and we ask about
+ group 23, that user should be found.
+
+=cut
+
+Users must be able to delegate individual rights
+
+ * Is it that users can delegate any and all rights but it's
+ only rights they _have_ which actually grant rights.
+
+rights must not be redelegated
+
+users must be able to create groups to which rights can be delegated.
+
+Only users who have the "delegate rights" right can delegate rights.
+
+
+When a user's right to do something is revoked, the delegation must
+be revoked
+
+ * For any delegated ACL check, the delegator's right must be
+ checked immediately after the delegatee's right.
+ If a user has had a right delegated by multiple parties,
+ this may mean that we need to actually loop through and check
+ a bunch of possible delegations. Or can we craft a "has delegated
+ right" ACL check.
+
+
+
+
+
+
+
+ACL 1 Group Q has the right to Frob ObjectI.
+ACL 2 User A has the right "DelegateRights"
+
+Group Q has the member Group S
+Group S has the member Group R
+Group S has the member Group T
+Group R has the member user A
+Group T has the member user A
+
+User A delegates to Group P the right to Frob ObjectI
+
+ New ACL rule:
+
+ ACL 3: Group P has the right to Frob ObjectI
+ as delegated from ACL1 by User A
+
+
+In the case where ACL1 is revoked:
+
+ find all acls which are delegated from ACL1.
+ Delete them
+
+In the case where User A is removed from group R
+
+ Get the list of all groups that A was in by way of group R before the removal
+ Get the list of all groups that A is in _after_ the removal.
+
+ Find all the ACEs granted to each group that A is no longer in.
+ For each ACE in that list, find all the rights that A has delegated.
+ Whack them.
+
+In the case where Group S is removed from group Q
+
+
+ Get a list of all groups that S was in by way of Q before the removal
+ Call this list O.
+
+ For each user X who's a member of S (directly or indirectly):
+ Get a list of all groups that X is in after removal.
+ For each group in O that X is no longer a member of:
+ Find all ACEs granted to O
+ For each ACE, look up all the delegations that X has made.
+ For each delegation
+ WHACK IT
diff --git a/rt/docs/design_docs/evil_plans b/rt/docs/design_docs/evil_plans
index 34b9f81..5b5cc58 100644
--- a/rt/docs/design_docs/evil_plans
+++ b/rt/docs/design_docs/evil_plans
@@ -3,8 +3,7 @@ Current planned 2.2 feature list. subject to change.
Core
-Should Make "Owner" a watcher type, rather than a special ticket attribute,
- under the hood. This wins for ACL and code consistency reasons.
+
Web UI
@@ -67,8 +66,6 @@ nice Scrips could apply to a list of queues, rather than just one queue or
Custom fields
-Must "KeywordSelects" become "Custom Fields"
-Should String and multi-string custom fields.
Nice Date custom fields
Nice Some way to order and group custom fields.
Nice Default values
@@ -79,8 +76,6 @@ Nice Make custom fields apply to an enumerated list of queues,
Web infrastructure
-Must Full fastcgi support.
-
Installation
@@ -116,7 +111,7 @@ Nice Export full ticket metadata and history as XML
Note: I currently favor the REST philosophy that GET and POST to specific,
defined URLs provides everything one needs to build comprehensive
web services without the massive added complexity of a SOAP or XML-RPC
- framework.
+ framework. Sadly, the world doesn't agree with me
ACLs:
diff --git a/rt/docs/design_docs/groups_notes b/rt/docs/design_docs/groups_notes
new file mode 100644
index 0000000..234fd37
--- /dev/null
+++ b/rt/docs/design_docs/groups_notes
@@ -0,0 +1,88 @@
+CREATE TABLE Prinicpals (
+ id int auto_increment
+ PrincipalType VARCHAR(16) not_null,
+ PrincipalId int # foreign key to Users or Groups, depending
+)
+
+CREATE TABLE Groups (
+ id int auto_increment,
+ Domain varchar(255),
+ Instance varchar(16),
+ Name varchar(255),
+ Description varchar(255),
+);
+CREATE TABLE ACL (
+ id INTEGER NOT NULL AUTO_INCREMENT,
+ Principal integer NULL , #Foreign key to principals
+ RightName varchar(25) NULL ,
+ RightDomain varchar(25) NULL ,
+ RightInstance integer NULL ,
+ PRIMARY KEY (id)
+);
+
+CREATE TABLE GroupMembers (
+ id int auto_increment,
+ Group int, # foreign key to Principals
+ Member int # foreign key to Principals
+)
+
+create table GroupMembersCache (
+ id int auto_increment,
+ Group int, # foreign key to Principals
+ Member int, # foreign key to Principals
+ Via int, #foreign key to g_m_u
+)
+
+insert into principals values ('bubbles);
+insert into principals values ('fubar');
+insert into principals values ('sheeri');
+insert into principals values ('sgw');
+
+insert into principals values ('staff');
+insert into principals values ('sysadmin');
+insert into principals values ('senior admin');
+
+
+insert into group_members values(1, 'staff', 'bubbles');
+insert into group_members values(2, 'sysadmin', 'sheeri');
+insert into group_members values(3,'senior admin', 'sgw');
+insert into group_members values(4,'senior admin', 'fubar');
+insert into group_members values(5, 'sysadmin', 'senior admin')
+
+Groups
+
+
+
+Domain Queues
+Instance <queueid#>
+Name AdminCc, Cc
+
+/Queues/1/AdminCc
+/Queues/3/Cc
+
+Domain Tickets
+Instance <#n>
+Name Owner, Requestor, Cc, AdminCc
+
+/Tickets/1/Owner
+/Tickets/1/Requestor
+/Tickets/1/Cc
+ Has members: /Queues/whatever queue the ticket has/Cc
+/Tickets/1/AdminCc
+ Has members: /Queues/whatever queue the ticket has/AdminCc
+
+
+Domain Users
+Instance <userid>
+
+/Users/1/MyDelegates
+/Users/1/MyOtherDelegates
+
+
+Domain System
+Name Admins, AdminManagers
+
+/System/Administrators
+/System/Blah
+
+
diff --git a/rt/docs/design_docs/recursive_group_membership_algorithm b/rt/docs/design_docs/recursive_group_membership_algorithm
new file mode 100644
index 0000000..250b9ad
--- /dev/null
+++ b/rt/docs/design_docs/recursive_group_membership_algorithm
@@ -0,0 +1,109 @@
+Group A has members 1, 2, 3
+
+ Cached members 1 is a member of A via ""
+ 2 is a member of A via ""
+ 3 is a member of A via ""
+
+
+Group B has members A, 4, 5
+
+ Cached members: 4 is a member of B via "" $1
+ 5 is a member of B via "" $2
+ A is a member of B via "" $3
+ 1 is a member of B via "$3" $4
+ 2 is a member of B via "$3" $5
+ 3 is a member of B via "$3" $6
+
+Group C has members A, B, 6
+ 6 is a member of C via "" $7
+ A is a member of C via "" $8
+ 1 is a member of C via $8 $9
+ 2 is a member of C via $8 $10
+ 3 is a member of C via $8 $11
+ B is a member of C via "" $12
+ 4 is a member of C via $12 $13
+ 5 is a member of C via $12 $14
+ A is a member of C via $12 $15
+ 1 is a member of C via $15 $16
+ 2 is a member of C via $15 $17
+ 3 is a member of C via $15 $18
+
+
+
+Group D has members A, C
+
+ A is a member of D via "" $19
+ 1 is a member of D via $19 $20
+ 2 is a member of D via $19 $21
+ 3 is a member of D via $19 $22
+ C is a member of D via "" $23
+ 6 is a member of D via $23 $24
+ A is a member of D via $23 $25
+ 1 is a member of D via $25 $26
+ 2 is a member of D via $25 $27
+ 3 is a member of D via $25 $28
+ B is a member of D via $23 $29
+ 4 is a member of D via $29 $30
+ 5 is a member of D via $29 $31
+ A is a member of D via $29 $32
+ 1 is a member of D via $32 $33
+ 2 is a member of D via $32 $34
+ 3 is a member of D via $32 $35
+
+
+
+Adding a new user, 7, to group A.
+
+
+ Add the user to group A in the groups table.
+
+ Find all entries for group A in the cache table.
+
+ For each entry in that list:
+ Add "7 is a member of $entry->top via $entry->id"
+
+Deleting a user, 7, from group A:
+
+ Remove the user from group A in the groups table.
+ find all entries in the cache table where the principal id is user 7 and
+ the parent id is A. (requires a self join)
+ nuke them
+
+ Alternatively:
+ find all entries for A in the cache table.
+ For each one, find the child whose id is 7.
+ Nuke it
+
+
+Adding a group, B to group D.
+
+ Add group B as a member of D in the groups table.
+ In the cache table:
+ $id = Add group B as a member of D via ""
+
+ For each member of group B (4, 5, A):
+
+ $sid= 4 is a member of D via $id
+ $sid= 5 is a member of D via $id
+ $sid= A is a member of D via $id
+
+ if the member is a group itself, recurse down:
+
+ 1 is a member of D via $sid
+ 2 is a member of D via $sid
+ 3 is a member of D via $sid
+
+ Find all places where D is a member of $foo.
+ Repeat the above procedure, substituting $foo for D
+ and making $id D's id.
+
+Removing B as a member of D:
+
+ Remove B as a member of D in the groups table.
+ Find all references to D in the pseudogroups table.
+ Find all children of D which are B:
+ Recurse down with the following algorithm:
+ If it's a user, delete it.
+ If it's a group, recurse through each member,
+ deleting its children and then deleting the
+ group itself.
diff --git a/rt/docs/design_docs/rql_parser_machine.graphviz b/rt/docs/design_docs/rql_parser_machine.graphviz
new file mode 100644
index 0000000..36463ec
--- /dev/null
+++ b/rt/docs/design_docs/rql_parser_machine.graphviz
@@ -0,0 +1,32 @@
+
+/* GraphViz graph representing the state diagram of the RQL parser.
+*/
+
+digraph G {
+
+ PAREN -> PAREN;
+ PAREN -> KEYWORD;
+ PAREN -> AGGREG;
+
+ AGGREG -> KEYWORD;
+ AGGREG -> PAREN;
+
+ KEYWORD -> OP;
+
+ OP -> VALUE;
+
+ VALUE -> PAREN;
+ VALUE -> AGGREG;
+
+/*
+ Blue lines represent added complexity of q[IN (x,y,z)] support.
+ The only place that the "blue tree" can be entered is at IN, and
+ exited at PAREN.
+*/
+ KEYWORD -> IN [color=blue];
+ IN -> PAREN [color=blue];
+ PAREN -> VALUE [color=blue];
+ VALUE -> COMMA [color=blue];
+ COMMA -> VALUE [color=blue];
+ VALUE -> PAREN [color=blue];
+}
diff --git a/rt/docs/design_docs/string-extraction-guide.txt b/rt/docs/design_docs/string-extraction-guide.txt
new file mode 100644
index 0000000..bd60a43
--- /dev/null
+++ b/rt/docs/design_docs/string-extraction-guide.txt
@@ -0,0 +1,100 @@
+# $File: //depot/RT/rt-devel/docs/design_docs/string-extraction-guide.txt $ $Author: ivan $
+# $Revision: 1.1 $ $Change: 1431 $ $DateTime: 2002/10/15 17:24:45 $
+
+Run 'p4 edit lib/RT/I18N/zh_tw.pm' and 'perl l10n.pl' to add new
+extractions to the zh_tw.pm.
+
+Edit lib/RT/I18N/zh_tw.pm for chinese counterparts.
+
+Attached is a copy of the freshly rewritten string extraction style guide.
+Please point out anything that's unclear or underspecified. I
+localized a number of the core modules in RT 2.1.3 (Starting with
+Queue_Overlay.pm). I only touched a couple of the web templates in the
+Elements/ directory of the web ui.
+
+RT String extraction styleguide:
+
+Web templates:
+
+Templates should use the /l filtering component to call the localisation
+framework
+
+The string Foo!
+
+Should become <&|/l&>Foo!</&>
+
+All newlines should be removed from localized strings, to make it easy to
+grep the codebase for strings to be localized
+
+The string Foo
+ Bar
+ Baz
+
+Should become <&|/l&>Foo Bar Baz</&>
+
+
+Variable subsititutions should be moved to Locale::MakeText format
+
+The string Hello, <%$name %>
+
+should become <&|/l, $name &>Hello, [_1]</&>
+
+
+Multiple variables work just like single variables
+
+The string You found <%$num%> tickets in queue <%$queue%>
+
+should become <&|/l, $num, $queue &>You found [_1] tickets in queue [_2]</&>
+
+When subcomponents are called in the middle of a phrase, they need to be escaped
+too:
+
+The string <input type="submit" value="New ticket in">&nbsp<& /Elements/SelectNewTicketQueue&>
+
+should become <&|/l, $m->scomp('/Elements/SelectNewTicketQueue')&><input type="submit" value="New ticket in">&nbsp;[_1]</&>
+
+
+
+There are places inside the web ui where strings are defined, which need to be
+localised. it is important to note here that each localized string is split out
+onto its own line, but never split across two lines and two localized strings
+are never included on the same line. It is also important to note
+that this will genereate code which will not work in RT 2.1.3. I need
+to add a bit of framework to make it work in 2.1.4
+
+
+The string <& /Elements/TitleBoxStart, width=> "40%", titleright => "RT $RT::VERSION for $RT::rtname", title => 'Login' &>
+
+should become <& /Elements/TitleBoxStart,
+ width=> "40%",
+ titleright => loc("RT [_1] for [_2]",$RT::VERSION, $RT::rtname),
+ title => loc('Login'),
+ &>
+
+
+
+
+
+
+Within RT's core code, every module has a localization handle available through the 'loc' method:
+
+The code return ( $id, "Queue created" );
+
+should become return ( $id, $self->loc("Queue created") );
+
+When returning or localizing a single string, the "extra" set of parenthesis () should be omitted.
+
+The code return ("Subject changed to ". $self->Data );
+
+should become return $self->loc( "Subject changed to [_1]", $self->Data );
+
+
+It is important not to localize the names of rights or statuses within RT's core, as there is logic that depends on them as string identifiers. The proper place to localize these values is when they're presented for display in the web or commandline interfaces.
+
+
+
+
+
+--
+http://www.bestpractical.com/products/rt -- Trouble Ticketing. Free.
+
diff --git a/rt/docs/design_docs/ticket_templates b/rt/docs/design_docs/ticket_templates
new file mode 100644
index 0000000..7850edf
--- /dev/null
+++ b/rt/docs/design_docs/ticket_templates
@@ -0,0 +1,16 @@
+===Create-Ticket: foo
+ Subject: APPROVE <%TOP-Subject%>
+ Status: status
+ Queue: <%TOP-Queue%>
+ Owner: <%TOP-Owner%>
+ Depends-on: <%TOP-Id%>
+ Child-of: <%TOP-Id%>
+ Refers-to: <%TOP-Id%>
+ Content-Type: text/plain
+ Content: This is content
+blah
+blah
+blah
+===Create-Ticket: bar
+Subject: <%foo-Subject%>
+