Skip to content

Commit

Permalink
Issue #1295: added a stub for a S3 article storage backend
Browse files Browse the repository at this point in the history
  • Loading branch information
bschmalhofer committed Oct 7, 2021
1 parent 07e0244 commit e6f9c6f
Show file tree
Hide file tree
Showing 5 changed files with 343 additions and 10 deletions.
301 changes: 301 additions & 0 deletions Kernel/System/Ticket/Article/Backend/MIMEBase/ArticleStorageS3.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,301 @@
# --
# OTOBO is a web-based ticketing system for service organisations.
# --
# Copyright (C) 2019-2021 Rother OSS GmbH, https://otobo.de/
# --
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later version.
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# --

package Kernel::System::Ticket::Article::Backend::MIMEBase::ArticleStorageS3;

use strict;
use warnings;
use v5.24;
use namespace::autoclean;
use utf8;

use parent qw(Kernel::System::Ticket::Article::Backend::MIMEBase::Base);

# core modules
use MIME::Base64;

# CPAN modules
use MIME::Words qw(:all);
use Amazon::S3::Thin;

# OTOBO modules
use Kernel::System::VariableCheck qw(:all);

our @ObjectDependencies = (
'Kernel::System::Log',
'Kernel::System::Main',
);

=head1 NAME
Kernel::System::Ticket::Article::Backend::MIMEBase::ArticleStorageS3 - S3 based ticket article storage interface
=head1 DESCRIPTION
This class provides functions to manipulate ticket articles in the database.
The methods are currently documented in L<Kernel::System::Ticket::Article::Backend::MIMEBase>.
Inherits from L<Kernel::System::Ticket::Article::Backend::MIMEBase::Base>.
See also L<Kernel::System::Ticket::Article::Backend::MIMEBase::ArticleStorageFS> and
L<Kernel::System::Ticket::Article::Backend::MIMEBase::ArticleStorageDB>.
=cut

sub ArticleDelete {
my ( $Self, %Param ) = @_;

# check needed stuff
for my $Item (qw(ArticleID UserID)) {
if ( !$Param{$Item} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need $Item!"
);

return;
}
}

# delete attachments
$Self->ArticleDeleteAttachment(
ArticleID => $Param{ArticleID},
UserID => $Param{UserID},
);

# delete plain message
$Self->ArticleDeletePlain(
ArticleID => $Param{ArticleID},
UserID => $Param{UserID},
);

return 1;
}

sub ArticleDeletePlain {
my ( $Self, %Param ) = @_;

# check needed stuff
for my $Item (qw(ArticleID UserID)) {
if ( !$Param{$Item} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need $Item!"
);

return;
}
}

# delete attachments
# TODO_S3

# the S3 backend does not support storing articles in mixed backends
return 1;
}

sub ArticleDeleteAttachment {
my ( $Self, %Param ) = @_;

# check needed stuff
for my $Item (qw(ArticleID UserID)) {
if ( !$Param{$Item} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need $Item!"
);

return;
}
}

# delete attachments
# TODO_S3

# the S3 backend does not support storing articles in mixed backends
return 1;
}

sub ArticleWritePlain {
my ( $Self, %Param ) = @_;

# check needed stuff
for my $Item (qw(ArticleID Email UserID)) {
if ( !$Param{$Item} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need $Item!"
);

return;
}
}

# write article to S3
# TODO_S3

return 1;
}

sub ArticleWriteAttachment {
my ( $Self, %Param ) = @_;

# check needed stuff
for my $Item (qw(Filename ContentType ArticleID UserID)) {
if ( !IsStringWithData( $Param{$Item} ) ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need $Item!"
);

return;
}
}

$Param{Filename} = $Kernel::OM->Get('Kernel::System::Main')->FilenameCleanUp(
Filename => $Param{Filename},
Type => 'Local',
NoReplace => 1,
);

my $NewFileName = $Param{Filename};
my %UsedFile;
my %Index = $Self->ArticleAttachmentIndex(
ArticleID => $Param{ArticleID},
);

for my $IndexFile ( sort keys %Index ) {
$UsedFile{ $Index{$IndexFile}->{Filename} } = 1;
}
for ( my $i = 1; $i <= 50; $i++ ) {
if ( exists $UsedFile{$NewFileName} ) {
if ( $Param{Filename} =~ /^(.*)\.(.+?)$/ ) {
$NewFileName = "$1-$i.$2";
}
else {
$NewFileName = "$Param{Filename}-$i";
}
}
}

# get file name
$Param{Filename} = $NewFileName;

# get attachment size
$Param{Filesize} = bytes::length( $Param{Content} );

# set content id in angle brackets
if ( $Param{ContentID} ) {
$Param{ContentID} =~ s/^([^<].*[^>])$/<$1>/;
}

my $Disposition;
my $Filename;
if ( $Param{Disposition} ) {
( $Disposition, $Filename ) = split ';', $Param{Disposition};
}
$Disposition //= '';

# write attachment to db
# TODO_S3

return 1;
}

sub ArticlePlain {
my ( $Self, %Param ) = @_;

# check needed stuff
if ( !$Param{ArticleID} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need ArticleID!"
);

return;
}

# prepare/filter ArticleID
$Param{ArticleID} = quotemeta( $Param{ArticleID} );
$Param{ArticleID} =~ s/\0//g;

# TODO_S3

# the S3 backend does not support storing articles in mixed backends
return 1;
}

sub ArticleAttachmentIndexRaw {
my ( $Self, %Param ) = @_;

# check needed stuff
if ( !$Param{ArticleID} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'Need ArticleID!'
);

return;
}

my %Index;
my $Counter = 0;

# TODO_S3

# return existing index
return %Index if %Index;

# the S3 backend does not support storing articles in mixed backends
return 1;
}

sub ArticleAttachment {
my ( $Self, %Param ) = @_;

# check needed stuff
for my $Item (qw(ArticleID FileID)) {
if ( !$Param{$Item} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need $Item!"
);

return;
}
}

# prepare/filter ArticleID
$Param{ArticleID} = quotemeta( $Param{ArticleID} );
$Param{ArticleID} =~ s/\0//g;

# get attachment index
my %Index = $Self->ArticleAttachmentIndex(
ArticleID => $Param{ArticleID},
);

return if !$Index{ $Param{FileID} };

my %Data = %{ $Index{ $Param{FileID} } };

# TODO_S3

return %Data if defined $Data{Content};

# the S3 backend does not support storing articles in mixed backends
return;
}

1;
16 changes: 16 additions & 0 deletions bin/otobo.CheckModules.pl
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ =head1 DESCRIPTION

# defines a set of features considered standard for docker environments
my %IsDockerFeature = (
'aws' => 1,
'db:mysql' => 1,
'db:odbc' => 1,
'db:postgresql' => 1,
Expand All @@ -192,6 +193,7 @@ =head1 DESCRIPTION
my %FeatureDescription = (
'aaacore' => 'Required packages',
'apache' => 'Recommended features for setups using apache',
'aws' => 'Amazon Web Services, currently only S3',
'db' => 'Database support (installing one is required)',
'db:mysql' => 'Support for database MySQL',
'db:odbc' => 'Support for database access via ODBC',
Expand Down Expand Up @@ -575,6 +577,20 @@ =head1 DESCRIPTION
},
},

# Feature aws
{
Module => 'Amazon::S3::Thin',
Features => ['aws'],
Comment => 'Required for article storage in S3',
InstTypes => {
aptget => undef,
emerge => undef,
yum => undef,
zypper => undef,
ports => undef,
},
},

# Feature db
{
Module => 'DBD::mysql',
Expand Down
9 changes: 9 additions & 0 deletions cpanfile
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@ feature 'apache:mod_perl', 'Suppport for apache:mod_perl' => sub {

};

feature 'aws', 'Amazon Web Services, currently only S3' => sub {
# Required for article storage in S3
requires 'Amazon::S3::Thin';

};

feature 'db:mysql', 'Support for database MySQL' => sub {
# Required to connect to a MySQL database.
requires 'DBD::mysql';
Expand Down Expand Up @@ -242,6 +248,9 @@ feature 'mail:ssl', 'Suppport for mail:ssl' => sub {
};

feature 'optional', 'Suppport for optional' => sub {
# Required for article storage in S3
requires 'Amazon::S3::Thin';

# Required to connect to a MySQL database.
requires 'DBD::mysql';

Expand Down
6 changes: 6 additions & 0 deletions cpanfile.docker
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,12 @@ requires 'Const::Fast';
# Feature 'apache:mod_perl' is not needed for Docker


# feature 'aws', 'Amazon Web Services, currently only S3' => sub {
# Required for article storage in S3
requires 'Amazon::S3::Thin';

# };

# feature 'db:mysql', 'Support for database MySQL' => sub {
# Required to connect to a MySQL database.
requires 'DBD::mysql';
Expand Down
Loading

0 comments on commit e6f9c6f

Please sign in to comment.