Yeah sure attached .. Its basic and far from perfect, it was my first attempt writing soap service and just to serve my immediate needs, I Just hope somebody can use it as a base and develop a full service that can be used by .net and jave clients, The REST interface is very good, but all the rage (what managers like) is SOAP and web services etc .. Please bare in mind it includes some of our custom status'es , which you may have to remove ..
Regards;
Roy

Torsten Brumm wrote:
Hi Roy,

can you also share this soap services, the "old" one from BPS seams to be
outdated or only for rt2x i think.

Torsten

2006/9/8, Roy El-Hames <[EMAIL PROTECTED]>:

rt-3.6.1/Apache2
I've written a simple soap service  for rt that can communicate with
windows .net client via a wsdl file, however I can't find the best way
to send attachments, as rt will expect a mime object that combine the
update/create text with the attachment, I'll need to create this object
on the server (rt side), can anyone suggest the best way to do this, the
.net developers would prefer to send attachments separate as a DIME
Referenced binary.
Thanks;
Roy
_______________________________________________
http://lists.bestpractical.com/cgi-bin/mailman/listinfo/rt-users

Community help: http://wiki.bestpractical.com
Commercial support: [EMAIL PROTECTED]


Discover RT's hidden secrets with RT Essentials from O'Reilly Media.
Buy a copy at http://rtbook.bestpractical.com





#!/usr/bin/perl

use lib ("/opt/rt3/local/html/SOAP");
use RTSoap;
use SOAP::Transport::HTTP;

SOAP::Transport::HTTP::CGI
  -> dispatch_to('/opt/rt3/local/html/SOAP','RTSoap')
  -> handle;
<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions name="RTSoap" 
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/";
 xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/";
 xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/";
 xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"; xmlns:tns="urn:RTSoap"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema";
 xmlns:xsd-ENV="http://schemas.xmlsoap.org/soap/envelope/";
 xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/";
 xmlns:http="http://schemas.xmlsoap.org/wsdl/"; targetNamespace="urn:RTSoap"
 xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/";>
  <wsdl:types>
    <xsd:schema elementFormDefault="qualified" targetNamespace="urn:RTSoap">
      <xsd:element name="GetTicket">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element minOccurs="0" maxOccurs="1" name="Requester" 
type="xsd:string" />
            <xsd:element minOccurs="1" maxOccurs="1" name="TicketId" 
type="xsd:int" />
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>

      <xsd:element name="GetTicketsByRequestor">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element minOccurs="1" maxOccurs="1" name="Requester" 
type="xsd:string" />
            <xsd:element minOccurs="1" maxOccurs="1" name="Status" 
type="xsd:string" />
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>

     <xsd:element name="CreateTicket">
      <xsd:complexType>
                <xsd:sequence>
                        <xsd:element name="Requester" type="xsd:string" />
                        <xsd:element name="Cc" type="xsd:string" />
                        <xsd:element name="Subject" type="xsd:string" />
                        <xsd:element name="Queue" type="xsd:string" />
                        <xsd:element name="Attachment" type="xsd:string" />
                        <xsd:element name="Text" type="xsd:string" />
                </xsd:sequence>
       </xsd:complexType>
    </xsd:element>

     <xsd:element name="UpdateTicket">
      <xsd:complexType>
                <xsd:sequence>
                        <xsd:element name="Requester" type="xsd:string" />
                        <xsd:element name="Cc" type="xsd:string" />
                        <xsd:element name="TicketId" type="xsd:int" />
                        <xsd:element name="Subject" type="xsd:string" />
                        <xsd:element name="Attachment" type="xsd:string" />
                        <xsd:element name="Text" type="xsd:string" />
                        <xsd:element name="Status" type="xsd:string"/>
                </xsd:sequence>
      </xsd:complexType>
    </xsd:element>

      <xsd:element name="GetTicketResponse">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element minOccurs="0" maxOccurs="1" name="Basics" 
type="tns:Basics" />
            <xsd:element minOccurs="0" maxOccurs="1" name="Updates" 
type="tns:Updates" />
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>

      <xsd:element name="GetTicketsByRequestorResponse">
        <xsd:complexType>
          <xsd:sequence>
                <xsd:element minOccurs="0" maxOccurs="1" name="TicketsList" 
type="tns:TicketsList" />
          </xsd:sequence>
       </xsd:complexType>
      </xsd:element>

      <xsd:element name="CreateTicketResponse">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element minOccurs="0" maxOccurs="1" name="TicketId" 
type="tns:TicketId" />
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>

      <xsd:element name="UpdateTicketResponse">
        <xsd:complexType>
          <xsd:sequence>
                <xsd:element minOccurs="0" maxOccurs="1" name="UpdateStatus" 
type="xsd:string" />
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>

     <xsd:complexType name="TicketId">
        <xsd:sequence>
         <xsd:element minOccurs="1" maxOccurs="1" name="TicketId" 
type="xsd:string" />
        </xsd:sequence>
     </xsd:complexType>

      <xsd:complexType name="Basics">
        <xsd:sequence>
          <xsd:element minOccurs="1" maxOccurs="1" name="TicketId" 
type="xsd:string" />
          <xsd:element minOccurs="0" maxOccurs="1" name="Subject" 
type="xsd:string" />
          <xsd:element minOccurs="0" maxOccurs="1" name="Status" 
type="xsd:string" />
          <xsd:element minOccurs="0" maxOccurs="1" name="LastUpdateTime" 
type="xsd:string" />
          <xsd:element minOccurs="0" maxOccurs="1" name="ResolvedTime" 
type="xsd:string" />
          <xsd:element minOccurs="0" maxOccurs="1" name="Requesters" 
type="xsd:string" />
        </xsd:sequence>
      </xsd:complexType>

      <xsd:complexType name="Update">
        <xsd:sequence>
                <xsd:element minOccurs="0" name="TransactionCreator" 
type="xsd:string" />
                <xsd:element minOccurs="0" name="TransactionCreated" 
type="xsd:string" />
                <xsd:element minOccurs="0" name="Correspondence" 
type="xsd:string" />
        </xsd:sequence>
      </xsd:complexType>

      <xsd:complexType name="Updates">
        <xsd:sequence>
               <xsd:element minOccurs="0" maxOccurs="unbounded" name="Update" 
type="tns:Update" />
        </xsd:sequence>
      </xsd:complexType>

      <xsd:complexType name="TicketParams">
        <xsd:sequence>
                <xsd:element minOccurs="0" name="TicketId" type="xsd:string" />
                <xsd:element minOccurs="0" name="Subject" type="xsd:string" />
                <xsd:element minOccurs="0" name="Status" type="xsd:string" />
        </xsd:sequence>
      </xsd:complexType>

      <xsd:complexType name="TicketsList">
        <xsd:sequence>
                <xsd:element minOccurs="0" maxOccurs="unbounded" 
name="TicketParams" type="tns:TicketParams" />
        </xsd:sequence>
      </xsd:complexType>

    </xsd:schema>
  </wsdl:types>
 <wsdl:message name="GetTicketSoapIn">
    <wsdl:part name="parameters" element="tns:GetTicket" />
  </wsdl:message>
  <wsdl:message name="GetTicketSoapOut">
    <wsdl:part name="parameters" element="tns:GetTicketResponse" />
  </wsdl:message>

  <wsdl:message name="GetTicketsByRequestorSoapIn">
    <wsdl:part name="parameters" element="tns:GetTicketsByRequestor" />
  </wsdl:message>
  <wsdl:message name="GetTicketsByRequestorSoapOut">
    <wsdl:part name="parameters" element="tns:GetTicketsByRequestorResponse" />
  </wsdl:message>

  <wsdl:message name="CreateTicketSoapIn">
    <wsdl:part name="parameters" element="tns:CreateTicket" />
  </wsdl:message>
  <wsdl:message name="CreateTicketSoapOut">
    <wsdl:part name="parameters" element="tns:CreateTicketResponse" />
  </wsdl:message>

  <wsdl:message name="UpdateTicketSoapIn">
    <wsdl:part name="parameters" element="tns:UpdateTicket" />
  </wsdl:message>
  <wsdl:message name="UpdateTicketSoapOut">
    <wsdl:part name="parameters" element="tns:UpdateTicketResponse" />
  </wsdl:message>

  <wsdl:portType name="ServiceSoap">

    <wsdl:operation name="GetTicket">
      <wsdl:input message="tns:GetTicketSoapIn" />
      <wsdl:output message="tns:GetTicketSoapOut" />
    </wsdl:operation>

    <wsdl:operation name="GetTicketsByRequestor">
      <wsdl:input message="tns:GetTicketsByRequestorSoapIn" />
      <wsdl:output message="tns:GetTicketsByRequestorSoapOut" />
    </wsdl:operation>

   <wsdl:operation name="CreateTicket">
      <wsdl:input message="tns:CreateTicketSoapIn" />
      <wsdl:output message="tns:CreateTicketSoapOut" />
    </wsdl:operation>

   <wsdl:operation name="UpdateTicket">
      <wsdl:input message="tns:UpdateTicketSoapIn" />
      <wsdl:output message="tns:UpdateTicketSoapOut" />
    </wsdl:operation>

  </wsdl:portType>

  <wsdl:binding name="ServiceSoap" type="tns:ServiceSoap">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http"; />

    <wsdl:operation name="GetTicket">
      <soap:operation soapAction="urn:RTSoap/GetTicket" style="document" />
      <wsdl:input>
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="GetTicketsByRequestor">
      <soap:operation soapAction="urn:RTSoap/GetTicketsByRequestor" 
style="document" />
      <wsdl:input>
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal" />
      </wsdl:output>
    </wsdl:operation>

    <wsdl:operation name="CreateTicket">
      <soap:operation soapAction="urn:RTSoap/CreateTicket" style="document" />
      <wsdl:input>
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal" />
      </wsdl:output>
    </wsdl:operation>

   <wsdl:operation name="UpdateTicket">
      <soap:operation soapAction="urn:RTSoap/UpdateTicket" style="document" />
      <wsdl:input>
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal" />
      </wsdl:output>
    </wsdl:operation>

  </wsdl:binding>
  <wsdl:binding name="ServiceSoap12" type="tns:ServiceSoap">
    <soap12:binding transport="http://schemas.xmlsoap.org/soap/http"; />

    <wsdl:operation name="GetTicket">
      <soap12:operation soapAction="urn:RTSoap/GetTicket" style="document" />
      <wsdl:input>
        <soap12:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap12:body use="literal" />
      </wsdl:output>
    </wsdl:operation>

    <wsdl:operation name="GetTicketsByRequestor">
      <soap12:operation soapAction="urn:RTSoap/GetTicketsByRequestor" 
style="document" />
      <wsdl:input>
        <soap12:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap12:body use="literal" />
      </wsdl:output>
    </wsdl:operation>

    <wsdl:operation name="CreateTicket">
      <soap12:operation soapAction="urn:RTSoap/Create" style="document" />
      <wsdl:input>
        <soap12:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap12:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
  <wsdl:operation name="UpdateTicket">
      <soap12:operation soapAction="urn:RTSoap/UpdateTicket" style="document" />
      <wsdl:input>
        <soap12:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap12:body use="literal" />
      </wsdl:output>
    </wsdl:operation>

 </wsdl:binding>
  <wsdl:service name="Service">
    <wsdl:port name="ServiceSoap" binding="tns:ServiceSoap">
      <soap:address location="http://YOURRTADDRESS/res.cgi"; />
    </wsdl:port>
    <wsdl:port name="ServiceSoap12" binding="tns:ServiceSoap12">
      <soap12:address location="http://YOURRTADDRESS/res.cgi"; />
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>


package RTSoap ;

use lib ( "/opt/rt3/lib", "/opt/rt3/local/lib" );
use RT;
use RT::Ticket;
use RT::Users;
CleanEnv;
RT::LoadConfig;
RT::Init;
our @ISA = qw( SOAP::Server::Parameters );

sub new {
        $self = shift;
        my $class = ref($self) || $self;
        bless {_tic => shift} => $class;
        return $class;
}

sub Hello {
        ### test function ##is soap lite working
        my $self = shift;
        my ($string) = @_;
        return "Hello " . $string;
}

sub RT_User {
        my ($address) = shift;
        unless ($address) {
                return (undef);
        }
        my $user = RT::CurrentUser->new();
        $user->LoadByEmail($address);
        unless ($user->Id){
                return undef;
        }
        return $user;
}

sub GetTicketsByRequestor {
        #### you get a requester and may get status resolved
        ## if you get status = resolved only return a list of resolved tickets 
else return all non resolved tickets for this requestor

        my $self = shift;
        my %args = %{pop->method};
        my $requestor = $args{'Requester'};
        my $status = $args{'Status'};
        my $error = undef;

        ## Get user
        my $CurrentUser = RT_User($requestor);
        if (!$CurrentUser) {
                $error = "Not RT user, verify email address";
                die $error;
        }
        $RT::Logger->error("Web service invoked do I get back here $requestor");
        my $tickets = new RT::Tickets($CurrentUser);
        if (!$tickets) {
                $error = "No tickets of this status for this user";
                die $error;
        }
        my @collection;
        $tickets->LimitWatcher(TYPE => 'Requestor', VALUE =>$requestor);
        if ($status =~ /resolved/) {
                $tickets->LimitStatus(VALUE => "resolved");
                $tickets->LimitStatus(VALUE => "completed");
        } else {
                $tickets->LimitStatus(VALUE => "open");
                $tickets->LimitStatus(VALUE => "new");
                $tickets->LimitStatus(VALUE => "stalled");
                $tickets->LimitStatus(VALUE => "re-opened");
                $tickets->LimitStatus(VALUE => "monitored");
        }
        $tickets->OrderBy(FIELD => 'id', ORDER => 'DESC');
        while (my $ticket = $tickets->Next) {
                my @list;
                @list = (
                        SOAP::Data->name("TicketParams" => \SOAP::Data->value(
                                
SOAP::Data->name('TicketId')->value($ticket->Id()),
                                
SOAP::Data->name('Subject')->value($ticket->Subject()),
                                
SOAP::Data->name('Status')->value($ticket->Status())))
                );
                push @collection,@list
        }
        if ([EMAIL PROTECTED]) {
                $error = "Failed to retrieve ticket list ";
                die $error;
        }
        return (
                SOAP::Data->name("TicketsList" => \SOAP::Data->value(
                        SOAP::Data->name('CallItWhatEver')->value(@collection)))
        );

}

sub GetTicket(){
        ### you get a ticket id return the ticket providing the supplied 
requestor is in this ticket requesters string
        use RT::Transactions;
        my $self = shift;
        my %args = %{pop->method};
        my $requestor = $args{'Requester'};
        my $ticketId = $args{'TicketId'};
        my $error = undef;
### debug
#       $RT::Logger->error("Web service invoked and my requestor is 
$requestor");
#####
        my @collection;
        my $CurrentUser = RT_User($requestor);
        if (!$CurrentUser) {
                $error = "Not RT user, verify email address";
                die $error;
        }
        my $ticket = new RT::Ticket($CurrentUser,$self->{_tic});
        $ticket->Load($ticketId);
        unless ( $ticket->id ) {
                $error = "Error loading ticket, maybe invalid ticket id" ;
                die $error;
        }
        if ($ticket->Id()){
                unless ($ticket->IsWatcher(Type => 'Requestor', PrincipalId => 
$CurrentUser->PrincipalId)) {
                        $error = "Permission denied. $requestor is not a 
requestor for this ticket";
                        die $error;
                }
                $Tid = $ticket->Id();
                $TSubject = $ticket->Subject();
                $TStatus = $ticket->Status();
                $TRequestors = 
$ticket->Requestors->MemberEmailAddressesAsString;
                $TLastUpdate = $ticket->LastUpdated;
                $TResolved = $ticket->Resolved;
                my $trans = RT::Transactions->new($RT::SystemUser);
                $trans->LimitToTicket($Tid);
                $trans->Limit(
                        FIELD    => 'Type',
                        OPERATOR => '=',
                        VALUE    => "Correspond"
                   );
                   $trans->Limit(
                        FIELD    => 'Type',
                        OPERATOR => '=',
                        VALUE    => "Create"
                   );
                while (my $tran = $trans->Next ) {
                        my $attachments = RT::Attachments->new($RT::SystemUser);
                        $attachments->Limit(FIELD    => 'TransactionId',
                                            OPERATOR => '=',
                                            VALUE    => $tran->Id()
                        );
                        $attachments->Limit(FIELD    => 'ContentType',
                                        OPERATOR => '=',
                                        VALUE    => 'text/plain'
                        );
                        $attachments->Limit(FIELD    => 'Content',
                                        OPERATOR => '!=',
                                        VALUE    => ''
                        );
                        my ($update,@updates) ;
                        while (my $attachment = $attachments->Next) {
                                my $aid = $attachment->Id() ;
                                my $atid = $attachment->TransactionId() ;
                                my $acontent = $attachment->Content();
                                $update = (
                                        
SOAP::Data->type('string')->name('Correspondence')->value($acontent)
                                );
                         push @updates,$update ;
                        }
                        my @t = (
                            SOAP::Data->name("Update" => \SOAP::Data->value(
                                        
SOAP::Data->type('string')->name('TransactionCreator')->value($tran->CreatorObj->Name),
                                        
SOAP::Data->type('string')->name('TransactionCreated')->value($tran->Created),
                                        
SOAP::Data->type('complexType')->name('Correspondence')->value(@updates)
                                        ))
                        );
                        push  @collection,@t ;
                }
        } else {
                $error = "Error loading ticket updates";
                die $error;
        }
        # format SOAP::Data Object and return
        return (
                SOAP::Data->name('Basics' => \SOAP::Data->value(
                        SOAP::Data->name('TicketId')->value($Tid),
                        SOAP::Data->name('Subject')->value($TSubject),
                        SOAP::Data->name('Status')->value($TStatus),

                        SOAP::Data->name('LastUpdateTime')->value($TLastUpdate),
                        SOAP::Data->name('ResolvedTime')->value($TResolved),
                        SOAP::Data->name('Requesters')->value($TRequestors))),
                SOAP::Data->name('Updates' => \SOAP::Data->value(
                        SOAP::Data->name('CallItWhatEver')->value(@collection)))
        );
}

sub CreateTicket {
        #### attachments handling is rubbish ... need looking at later 
        use MIME::Entity;
        my $MimeMessage;
        my $self = shift;
        my %args = %{pop->method};
        my $requestor = $args{'Requester'};
        my $cc = $args{'Cc'};
        my $queue = $args{'Queue'};
        my $subject = $args{'Subject'};
        my $txt = $args{'Text'};
        my $attach = $args{'Attachment'};
###### for debug purposes ###
        $RT::Logger->error("SOAPING:do I get text? ($txt)");
        if ($attach) {
                 $RT::Logger->error("SOAPING:I have attachment");
        }

############
        my $CurrentUser = RT_User($requestor);
        if (!$CurrentUser) {
                 $CurrentUser = $RT::SystemUser ; ### we need to create tickets 
for new users as well
        }

        if ($attach) {
                $MimeMessage = $attach;
        } else {
                $Mime = MIME::Entity->build(
                              From => $requestor,
                              Subject =>$subject,
                              Cc => $cc,
                              Type => 'text/plain',
                              Data => $txt
                        );
                 $MimeMessage = $Mime->stringify();
        }


        my $newticket = new RT::Ticket($CurrentUser);
        my $parser = RT::EmailParser->new();
        $parser->ParseMIMEEntityFromScalar($MimeMessage);
        #$parser->ParseMIMEEntityFromScalar($attach);

        my %create_args = (
                Queue => $queue,
                Requestor => $requestor,
                Cc => $cc,
                Subject => $subject,
                MIMEObj => $parser->Entity
                );

        my ( $id, $Trans, $ErrMsg ) = $newticket->Create(%create_args);
        unless ( $id && $Trans ) {
                die $ErrMsg ;
        }
                    return (SOAP::Data->name('TicketId' => \SOAP::Data->value(
                              SOAP::Data->name('TicketId')->value($id))));
}

sub UpdateTicket {
        ### only update if the supplied requester is the ticket requester 
        ### attachments attchments attachments 
        use MIME::Entity;
        my $MimeMessage;
        my $self = shift;
        my %args = %{pop->method};
        my $txt = $args{'Text'};
        my $attach = $args{'Attachment'};
        my $CurrentUser = RT_User($args{'Requester'});
        my $error = undef;
        if (!$CurrentUser) {
                $error = "Not RT user, verify email address";
                die $error;
        }

        if ($attach && $attach != '') {
                $MimMessage = $attach;
        } else {
                $Mime = MIME::Entity->build(
                              From => $requestor,
                              Subject =>$subject,
                              Cc => $cc,
                              Type => 'text/plain',
                              Data => $txt
                        );
                 $MimeMessage = $Mime->stringify();
        }

        my $ticket = new RT::Ticket($CurrentUser);
        $ticket->Load($args{'TicketId'}) ;
        unless ( $ticket->id ) {
                $error = "Error loading ticket, maybe invalid ticket id";
                die $error;
        }
        unless ($ticket->IsWatcher(Type => 'Requestor', PrincipalId => 
$CurrentUser->PrincipalId)) {
                        $error = "Permission denied. $requestor is not a 
requestor for this ticket";
                        die $error;
        }
        my $parser = RT::EmailParser->new();
        $parser->ParseMIMEEntityFromScalar($MimeMessage);
        my ($val,$msg);
        if ( $args{'Status'} && $args{'Status'} ne $ticket->Status ) {
                ( $val, $msg ) = $ticket->SetStatus( $args{'Status'} );
                if ($val == 0) {
                        $msg = "Failed to update status";
                        die $msg;
                }
        }
        if ($MimeMessage) {
                ( $val, $msg ) = $ticket->Correspond( MIMEObj => 
$parser->Entity,
                                                        CcMessageTo  => 
$args{'Cc'});
                if ($val == 0) {
                        $msg = "Failed to update ticket";
                        die $msg;
                }
        }
        return (SOAP::Data->name('UpdateStatus')->value("OK"));
}
1;



_______________________________________________
http://lists.bestpractical.com/cgi-bin/mailman/listinfo/rt-users

Community help: http://wiki.bestpractical.com
Commercial support: [EMAIL PROTECTED]


Discover RT's hidden secrets with RT Essentials from O'Reilly Media. 
Buy a copy at http://rtbook.bestpractical.com

Reply via email to