Embedding a file on a page using StreamResponse from another component.

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Embedding a file on a page using StreamResponse from another component.

NutterzUK
Hi,

I think I am doing something very, very wrong. What I have currently
works - but I get a feeling that it's not the best way of doing it.
I'm hoping for a little bit of advice again (sorry to ask so many
questions recently, and sorry this is a long one).

This is the issue:
I have some dynamic files with file paths which depend on the user.
Previously, all of those files existed on the context which was bad
news because it meant if a user knew the URL, they could download any
file. Without going into S3 servers for now (I can't unfortunately as
I have a monstrously huge pile of ethics forms to fill out if I want
to do that), I want to be able to embed these files on the page for a
user to see once they have logged in.

My solution has been to create a page named "FileStreamResponse" which
returns a StreamResponse from the onActivate method. I then can do the
following from another page class to get a link to that file.

 @Inject ComponentResources resources;
public Link getStaticFileLink() {
    return resources.createPageLink("util/FileStreamResponse", true);
}

In the TML, I can use that link to embed it. This works for one file,
which I have tested as "C:/file.xml" for now, but of course if anyone
visits the link for /util/FileStreamResponse they get the same file.
However, what I should be able to do is pass a parameter containing
information about which file to show to the FileStreamResponse page.

For my first attempt is to pass a parameter, I tried this:
return resources.createPageLink("util/FileStreamResponse", true, "C:/file.xml");

This creates a link like this:
http://localhost:8080/xyz/util/filestreamresponse/C:$002ffile.xml

If I pick that up in the onActivate for the page it works.

However, this isn't good because the the param is passed in the URL
which again means anyone can view that link, unless I put a lot of
permissions logic in that filestreamresponse class which already
exists elsewhere then i'm a little stuck.

So I know of one more solution to passing this parameter but it seems
like a bit too much of a "hack" for even me.
I create a setup method in the filestreamresponse page which takes in
a filename and sets it. It persists the property. Then I just use the
link to that page and it should show the correct file. Like this:

@InjectPage
private FileStreamResponse fsr;
@Inject ComponentResources resources;

public Link getStaticFileLink() {
    fsr.setup("C:/file.xml");
    return resources.createPageLink("util/FileStreamResponse", true);
}

I believe that now the user cannot change that parameter so it should
be safe. However, this doesn't seem right to me. It seems very.. very
bad and i'm sure someone will tell me exactly that. Another option is
to have the file which is requested stored in the User object which I
have in the sessionstate but again I don't think that is a good way to
do it.

If I put the logic for testing permissions in to the page class, I
still need to pass something to that page class to tell it which file
to show, and i'd rather that not show in the URL.

I'm sure others have had a similar problem and there is a standard way
to do this which I am missing, I would really appreciate any guidance.
Perhaps what I am doing is perfectly OK, but I suspect not as it leads
to issues such as, even if the user logs out, if the value is
persisted then they would see that file if re-visiting the link.
(Unless it is indeed stored in the User object).


Thanks,

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Embedding a file on a page using StreamResponse from another component.

NutterzUK
On a side note, both of my options (using the User object and using a
persisted field) will result in only being able to show one
StreamResponse at a time (otherwise they would both show the same). I
could extend this by having some kind of data structure (hashmap?) in
the User object and passing a token which is valid only to that user
as a parameter, but I think i'm so far off the mark.. there must be an
easier way.

On 24 October 2013 16:32, Steve <[hidden email]> wrote:

> Hi,
>
> I think I am doing something very, very wrong. What I have currently
> works - but I get a feeling that it's not the best way of doing it.
> I'm hoping for a little bit of advice again (sorry to ask so many
> questions recently, and sorry this is a long one).
>
> This is the issue:
> I have some dynamic files with file paths which depend on the user.
> Previously, all of those files existed on the context which was bad
> news because it meant if a user knew the URL, they could download any
> file. Without going into S3 servers for now (I can't unfortunately as
> I have a monstrously huge pile of ethics forms to fill out if I want
> to do that), I want to be able to embed these files on the page for a
> user to see once they have logged in.
>
> My solution has been to create a page named "FileStreamResponse" which
> returns a StreamResponse from the onActivate method. I then can do the
> following from another page class to get a link to that file.
>
>  @Inject ComponentResources resources;
> public Link getStaticFileLink() {
>     return resources.createPageLink("util/FileStreamResponse", true);
> }
>
> In the TML, I can use that link to embed it. This works for one file,
> which I have tested as "C:/file.xml" for now, but of course if anyone
> visits the link for /util/FileStreamResponse they get the same file.
> However, what I should be able to do is pass a parameter containing
> information about which file to show to the FileStreamResponse page.
>
> For my first attempt is to pass a parameter, I tried this:
> return resources.createPageLink("util/FileStreamResponse", true, "C:/file.xml");
>
> This creates a link like this:
> http://localhost:8080/xyz/util/filestreamresponse/C:$002ffile.xml
>
> If I pick that up in the onActivate for the page it works.
>
> However, this isn't good because the the param is passed in the URL
> which again means anyone can view that link, unless I put a lot of
> permissions logic in that filestreamresponse class which already
> exists elsewhere then i'm a little stuck.
>
> So I know of one more solution to passing this parameter but it seems
> like a bit too much of a "hack" for even me.
> I create a setup method in the filestreamresponse page which takes in
> a filename and sets it. It persists the property. Then I just use the
> link to that page and it should show the correct file. Like this:
>
> @InjectPage
> private FileStreamResponse fsr;
> @Inject ComponentResources resources;
>
> public Link getStaticFileLink() {
>     fsr.setup("C:/file.xml");
>     return resources.createPageLink("util/FileStreamResponse", true);
> }
>
> I believe that now the user cannot change that parameter so it should
> be safe. However, this doesn't seem right to me. It seems very.. very
> bad and i'm sure someone will tell me exactly that. Another option is
> to have the file which is requested stored in the User object which I
> have in the sessionstate but again I don't think that is a good way to
> do it.
>
> If I put the logic for testing permissions in to the page class, I
> still need to pass something to that page class to tell it which file
> to show, and i'd rather that not show in the URL.
>
> I'm sure others have had a similar problem and there is a standard way
> to do this which I am missing, I would really appreciate any guidance.
> Perhaps what I am doing is perfectly OK, but I suspect not as it leads
> to issues such as, even if the user logs out, if the value is
> persisted then they would see that file if re-visiting the link.
> (Unless it is indeed stored in the User object).
>
>
> Thanks,

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Embedding a file on a page using StreamResponse from another component.

Lance Java
In reply to this post by NutterzUK
Can't you just check the user has permissions before serving the file?
Throwing exception if they're not authorised.

BTW using local files is usually a bad idea (portability, scalability,
transactions etc). Have you considered storing in the db or a blobstore?
Reply | Threaded
Open this post in threaded view
|

Re: Embedding a file on a page using StreamResponse from another component.

Jens Breitenstein
In reply to this post by NutterzUK
Hi Steve!

Why not simply use the session? If the user has to authenticate anyway?

In case you want avoid a session you can create onetime tokens. Unfortunately checking token validity or detecting outdated tokens requires persistence somehow...

Jens

Von meinem iPhone gesendet

> Am 24.10.2013 um 17:44 schrieb Steve <[hidden email]>:
>
> On a side note, both of my options (using the User object and using a
> persisted field) will result in only being able to show one
> StreamResponse at a time (otherwise they would both show the same). I
> could extend this by having some kind of data structure (hashmap?) in
> the User object and passing a token which is valid only to that user
> as a parameter, but I think i'm so far off the mark.. there must be an
> easier way.
>
>> On 24 October 2013 16:32, Steve <[hidden email]> wrote:
>> Hi,
>>
>> I think I am doing something very, very wrong. What I have currently
>> works - but I get a feeling that it's not the best way of doing it.
>> I'm hoping for a little bit of advice again (sorry to ask so many
>> questions recently, and sorry this is a long one).
>>
>> This is the issue:
>> I have some dynamic files with file paths which depend on the user.
>> Previously, all of those files existed on the context which was bad
>> news because it meant if a user knew the URL, they could download any
>> file. Without going into S3 servers for now (I can't unfortunately as
>> I have a monstrously huge pile of ethics forms to fill out if I want
>> to do that), I want to be able to embed these files on the page for a
>> user to see once they have logged in.
>>
>> My solution has been to create a page named "FileStreamResponse" which
>> returns a StreamResponse from the onActivate method. I then can do the
>> following from another page class to get a link to that file.
>>
>> @Inject ComponentResources resources;
>> public Link getStaticFileLink() {
>>    return resources.createPageLink("util/FileStreamResponse", true);
>> }
>>
>> In the TML, I can use that link to embed it. This works for one file,
>> which I have tested as "C:/file.xml" for now, but of course if anyone
>> visits the link for /util/FileStreamResponse they get the same file.
>> However, what I should be able to do is pass a parameter containing
>> information about which file to show to the FileStreamResponse page.
>>
>> For my first attempt is to pass a parameter, I tried this:
>> return resources.createPageLink("util/FileStreamResponse", true, "C:/file.xml");
>>
>> This creates a link like this:
>> http://localhost:8080/xyz/util/filestreamresponse/C:$002ffile.xml
>>
>> If I pick that up in the onActivate for the page it works.
>>
>> However, this isn't good because the the param is passed in the URL
>> which again means anyone can view that link, unless I put a lot of
>> permissions logic in that filestreamresponse class which already
>> exists elsewhere then i'm a little stuck.
>>
>> So I know of one more solution to passing this parameter but it seems
>> like a bit too much of a "hack" for even me.
>> I create a setup method in the filestreamresponse page which takes in
>> a filename and sets it. It persists the property. Then I just use the
>> link to that page and it should show the correct file. Like this:
>>
>> @InjectPage
>> private FileStreamResponse fsr;
>> @Inject ComponentResources resources;
>>
>> public Link getStaticFileLink() {
>>    fsr.setup("C:/file.xml");
>>    return resources.createPageLink("util/FileStreamResponse", true);
>> }
>>
>> I believe that now the user cannot change that parameter so it should
>> be safe. However, this doesn't seem right to me. It seems very.. very
>> bad and i'm sure someone will tell me exactly that. Another option is
>> to have the file which is requested stored in the User object which I
>> have in the sessionstate but again I don't think that is a good way to
>> do it.
>>
>> If I put the logic for testing permissions in to the page class, I
>> still need to pass something to that page class to tell it which file
>> to show, and i'd rather that not show in the URL.
>>
>> I'm sure others have had a similar problem and there is a standard way
>> to do this which I am missing, I would really appreciate any guidance.
>> Perhaps what I am doing is perfectly OK, but I suspect not as it leads
>> to issues such as, even if the user logs out, if the value is
>> persisted then they would see that file if re-visiting the link.
>> (Unless it is indeed stored in the User object).
>>
>>
>> Thanks,
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Embedding a file on a page using StreamResponse from another component.

NutterzUK
Hi,

Thanks for the input, I really appreciate it. Unfortunately I do think
the files need saving as local files, for now at least. The reason
being that at the moment the project is really a prototype rather than
a fully blown system, but we do want it to be secure whilst we work.
The files may need to be easily directly editable on the server if
required and if it is all file based it also makes it easy to back up
for now.

I think I will save it along with the user object using onetime tokens
and see how well that works for now.

Thanks for your input, I really appreciate your help!
Steve

On 24 October 2013 17:37, [hidden email] <[hidden email]> wrote:

> Hi Steve!
>
> Why not simply use the session? If the user has to authenticate anyway?
>
> In case you want avoid a session you can create onetime tokens. Unfortunately checking token validity or detecting outdated tokens requires persistence somehow...
>
> Jens
>
> Von meinem iPhone gesendet
>
>> Am 24.10.2013 um 17:44 schrieb Steve <[hidden email]>:
>>
>> On a side note, both of my options (using the User object and using a
>> persisted field) will result in only being able to show one
>> StreamResponse at a time (otherwise they would both show the same). I
>> could extend this by having some kind of data structure (hashmap?) in
>> the User object and passing a token which is valid only to that user
>> as a parameter, but I think i'm so far off the mark.. there must be an
>> easier way.
>>
>>> On 24 October 2013 16:32, Steve <[hidden email]> wrote:
>>> Hi,
>>>
>>> I think I am doing something very, very wrong. What I have currently
>>> works - but I get a feeling that it's not the best way of doing it.
>>> I'm hoping for a little bit of advice again (sorry to ask so many
>>> questions recently, and sorry this is a long one).
>>>
>>> This is the issue:
>>> I have some dynamic files with file paths which depend on the user.
>>> Previously, all of those files existed on the context which was bad
>>> news because it meant if a user knew the URL, they could download any
>>> file. Without going into S3 servers for now (I can't unfortunately as
>>> I have a monstrously huge pile of ethics forms to fill out if I want
>>> to do that), I want to be able to embed these files on the page for a
>>> user to see once they have logged in.
>>>
>>> My solution has been to create a page named "FileStreamResponse" which
>>> returns a StreamResponse from the onActivate method. I then can do the
>>> following from another page class to get a link to that file.
>>>
>>> @Inject ComponentResources resources;
>>> public Link getStaticFileLink() {
>>>    return resources.createPageLink("util/FileStreamResponse", true);
>>> }
>>>
>>> In the TML, I can use that link to embed it. This works for one file,
>>> which I have tested as "C:/file.xml" for now, but of course if anyone
>>> visits the link for /util/FileStreamResponse they get the same file.
>>> However, what I should be able to do is pass a parameter containing
>>> information about which file to show to the FileStreamResponse page.
>>>
>>> For my first attempt is to pass a parameter, I tried this:
>>> return resources.createPageLink("util/FileStreamResponse", true, "C:/file.xml");
>>>
>>> This creates a link like this:
>>> http://localhost:8080/xyz/util/filestreamresponse/C:$002ffile.xml
>>>
>>> If I pick that up in the onActivate for the page it works.
>>>
>>> However, this isn't good because the the param is passed in the URL
>>> which again means anyone can view that link, unless I put a lot of
>>> permissions logic in that filestreamresponse class which already
>>> exists elsewhere then i'm a little stuck.
>>>
>>> So I know of one more solution to passing this parameter but it seems
>>> like a bit too much of a "hack" for even me.
>>> I create a setup method in the filestreamresponse page which takes in
>>> a filename and sets it. It persists the property. Then I just use the
>>> link to that page and it should show the correct file. Like this:
>>>
>>> @InjectPage
>>> private FileStreamResponse fsr;
>>> @Inject ComponentResources resources;
>>>
>>> public Link getStaticFileLink() {
>>>    fsr.setup("C:/file.xml");
>>>    return resources.createPageLink("util/FileStreamResponse", true);
>>> }
>>>
>>> I believe that now the user cannot change that parameter so it should
>>> be safe. However, this doesn't seem right to me. It seems very.. very
>>> bad and i'm sure someone will tell me exactly that. Another option is
>>> to have the file which is requested stored in the User object which I
>>> have in the sessionstate but again I don't think that is a good way to
>>> do it.
>>>
>>> If I put the logic for testing permissions in to the page class, I
>>> still need to pass something to that page class to tell it which file
>>> to show, and i'd rather that not show in the URL.
>>>
>>> I'm sure others have had a similar problem and there is a standard way
>>> to do this which I am missing, I would really appreciate any guidance.
>>> Perhaps what I am doing is perfectly OK, but I suspect not as it leads
>>> to issues such as, even if the user logs out, if the value is
>>> persisted then they would see that file if re-visiting the link.
>>> (Unless it is indeed stored in the User object).
>>>
>>>
>>> Thanks,
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [hidden email]
>> For additional commands, e-mail: [hidden email]
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Embedding a file on a page using StreamResponse from another component.

NutterzUK
Hi again,

Thanks for your help. I can't say how much I really appreciate the
help from the people who contribute here, a huge thank you all of you.
I've sent off the apache contributers licence agreement myself so that
hopefully, some time in the future if I can then I will improve some
of the documentation - if, and only if I feel I am able to improve it
with the knowledge I currently have (which is limited). After the
Apache contributors license is accepted, I assume I need to ask Howard
if it is ok for me to make minor updates to the documentation (e.g
fixing the odd typo or adding a short example here and there). @Howard
if you are watching, how does this work, and would this be ok?

About the problems I was having, just to let you know that I managed
to get this working using the single use tokens which are stored in
the user object. That means the URL won't work for anyone else or even
the same user. The logic is fairly simple and it is working well.

For anyone else wishing to do the same thing and as always, i'll
advise that my way of doing things is probably not the best way or the
only way,  the logic is like this (I welcome any comments):

When a user logs in, they get a sessionstate User object.
The User object has a hashmap of tokens/file paths <String,String>
When a file is required, the page requests a new token from the user
object via a method user.getToken(String filename).
This method adds an entry to the hashmap and returns the token (a
small, random string - although upon later consideration I see there
is no need for this to be random).
A getLink method in the page class where the file should be embedded
is responsible for requesting that token and returning a link to the
Stream Response page with a param to pass the token to it.
The link is then placed in the TML file using ${link}, allowing for
example <img src="${link}">.

I then have a set of blocks, each of which is responsible for
displaying a different type of media so that images, PDFs, code (using
pretty print javascript) or anything else can be shown by using that
link.
E.g:
<!-- PDF Viewer -->
<t:block id="pdf">
    <object width="100%" height="750px" type="application/pdf"
data="${FileLink}" id="pdf_content">
        <p>The PDF cannot be displayed, please update your
browser.</p>    </object>
</t:block>

The decision about which block to display is made by a delegate method
which looks at the filename to decide which block is most likely
appropriate.

Thanks,
Steve

On 24 October 2013 17:56, Steve <[hidden email]> wrote:

> Hi,
>
> Thanks for the input, I really appreciate it. Unfortunately I do think
> the files need saving as local files, for now at least. The reason
> being that at the moment the project is really a prototype rather than
> a fully blown system, but we do want it to be secure whilst we work.
> The files may need to be easily directly editable on the server if
> required and if it is all file based it also makes it easy to back up
> for now.
>
> I think I will save it along with the user object using onetime tokens
> and see how well that works for now.
>
> Thanks for your input, I really appreciate your help!
> Steve
>
> On 24 October 2013 17:37, [hidden email] <[hidden email]> wrote:
>> Hi Steve!
>>
>> Why not simply use the session? If the user has to authenticate anyway?
>>
>> In case you want avoid a session you can create onetime tokens. Unfortunately checking token validity or detecting outdated tokens requires persistence somehow...
>>
>> Jens
>>
>> Von meinem iPhone gesendet
>>
>>> Am 24.10.2013 um 17:44 schrieb Steve <[hidden email]>:
>>>
>>> On a side note, both of my options (using the User object and using a
>>> persisted field) will result in only being able to show one
>>> StreamResponse at a time (otherwise they would both show the same). I
>>> could extend this by having some kind of data structure (hashmap?) in
>>> the User object and passing a token which is valid only to that user
>>> as a parameter, but I think i'm so far off the mark.. there must be an
>>> easier way.
>>>
>>>> On 24 October 2013 16:32, Steve <[hidden email]> wrote:
>>>> Hi,
>>>>
>>>> I think I am doing something very, very wrong. What I have currently
>>>> works - but I get a feeling that it's not the best way of doing it.
>>>> I'm hoping for a little bit of advice again (sorry to ask so many
>>>> questions recently, and sorry this is a long one).
>>>>
>>>> This is the issue:
>>>> I have some dynamic files with file paths which depend on the user.
>>>> Previously, all of those files existed on the context which was bad
>>>> news because it meant if a user knew the URL, they could download any
>>>> file. Without going into S3 servers for now (I can't unfortunately as
>>>> I have a monstrously huge pile of ethics forms to fill out if I want
>>>> to do that), I want to be able to embed these files on the page for a
>>>> user to see once they have logged in.
>>>>
>>>> My solution has been to create a page named "FileStreamResponse" which
>>>> returns a StreamResponse from the onActivate method. I then can do the
>>>> following from another page class to get a link to that file.
>>>>
>>>> @Inject ComponentResources resources;
>>>> public Link getStaticFileLink() {
>>>>    return resources.createPageLink("util/FileStreamResponse", true);
>>>> }
>>>>
>>>> In the TML, I can use that link to embed it. This works for one file,
>>>> which I have tested as "C:/file.xml" for now, but of course if anyone
>>>> visits the link for /util/FileStreamResponse they get the same file.
>>>> However, what I should be able to do is pass a parameter containing
>>>> information about which file to show to the FileStreamResponse page.
>>>>
>>>> For my first attempt is to pass a parameter, I tried this:
>>>> return resources.createPageLink("util/FileStreamResponse", true, "C:/file.xml");
>>>>
>>>> This creates a link like this:
>>>> http://localhost:8080/xyz/util/filestreamresponse/C:$002ffile.xml
>>>>
>>>> If I pick that up in the onActivate for the page it works.
>>>>
>>>> However, this isn't good because the the param is passed in the URL
>>>> which again means anyone can view that link, unless I put a lot of
>>>> permissions logic in that filestreamresponse class which already
>>>> exists elsewhere then i'm a little stuck.
>>>>
>>>> So I know of one more solution to passing this parameter but it seems
>>>> like a bit too much of a "hack" for even me.
>>>> I create a setup method in the filestreamresponse page which takes in
>>>> a filename and sets it. It persists the property. Then I just use the
>>>> link to that page and it should show the correct file. Like this:
>>>>
>>>> @InjectPage
>>>> private FileStreamResponse fsr;
>>>> @Inject ComponentResources resources;
>>>>
>>>> public Link getStaticFileLink() {
>>>>    fsr.setup("C:/file.xml");
>>>>    return resources.createPageLink("util/FileStreamResponse", true);
>>>> }
>>>>
>>>> I believe that now the user cannot change that parameter so it should
>>>> be safe. However, this doesn't seem right to me. It seems very.. very
>>>> bad and i'm sure someone will tell me exactly that. Another option is
>>>> to have the file which is requested stored in the User object which I
>>>> have in the sessionstate but again I don't think that is a good way to
>>>> do it.
>>>>
>>>> If I put the logic for testing permissions in to the page class, I
>>>> still need to pass something to that page class to tell it which file
>>>> to show, and i'd rather that not show in the URL.
>>>>
>>>> I'm sure others have had a similar problem and there is a standard way
>>>> to do this which I am missing, I would really appreciate any guidance.
>>>> Perhaps what I am doing is perfectly OK, but I suspect not as it leads
>>>> to issues such as, even if the user logs out, if the value is
>>>> persisted then they would see that file if re-visiting the link.
>>>> (Unless it is indeed stored in the User object).
>>>>
>>>>
>>>> Thanks,
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: [hidden email]
>>> For additional commands, e-mail: [hidden email]
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [hidden email]
>> For additional commands, e-mail: [hidden email]
>>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]