Thursday, August 13, 2009

Secure Twitter Pic Part 1

Back Story
So after having our baby early, I wanted a convenient way to share pictures and updates to the family and I thought what better way than Twitter. So we set our baby up with a Twitter account and set it to protected. I found the best way to post pictures is through TwitPic, but found that when people post comments through TwitPic, the links show up on their Twitter page. Obviously this defeats the point of making her account protected since the main thing we wanted to protect was the pictures. We also know that it is extremely difficult to protect pictures on the Web, but we like to make it somewhat difficult for weirdos.

My solution to the problem is to write a small app so I can post a pic and a status from my iPhone and have it somewhat secure. I'm going to use Twitterizer as my C# Twitter framework, SQL 2008, and ASP.NET MVC. The flow will go like this...

if not authenticated to Twitter
authenticate

if a follower of the baby
show pic and allow comments
(comments will post to the viewer's Twitter like this: "@baby STP:1234 comment here")
Notice there is not a link to the picture, but still a reference so the baby knows which pic they're talking about
else
deny access to pic

As of right now, I have two services, ITwitterService & IUploadService, which look like this:

public interface ITwitterService
{
void Update(string status);
bool IsAuthenticated { get; }
}
public interface IUploadService
{
void Upload(HttpRequestBase request);
}
Here's my implementation:

public class
TwitterService : ITwitterService
{
private readonly Twitter _twitter;
private readonly string _username;
private readonly string _password;

public TwitterService(string username, string password) : this(username, password, null) {}

public TwitterService(string username, string password, string source)
{
_username = username;
_password = password;
if (string.IsNullOrEmpty(source))
_twitter = new Twitter(_username, _password);
else
_twitter = new Twitter(_username, _password, source);
}

public void Update(string status)
{
if (!string.IsNullOrEmpty(status))
_twitter.Status.Update(status);
}

public bool IsAllowed(string username)
{
var paras = new TwitterParameters();
paras.Add(TwitterParameterNames.ScreenName, username);
return _twitter.User.Followers(paras).Count > 0;
}

public bool IsAuthenticated
{
get { return Twitter.VerifyCredentials(_username, _password); }
}
}
public class UploadService : IUploadService
{
public void Upload(HttpRequestBase request)
{
   foreach (string file in request.Files)
{
var hpf = request.Files[file];
if (hpf.ContentLength == 0)
continue;
var savedFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Path.GetFileName(hpf.FileName));
hpf.SaveAs(savedFileName);
}
}
}
I ended up creating a helper service that takes the Twitter & Upload interfaces to do the upload and post at once…pretty simple.

public class
STPService
{
   private readonly ITwitterService _twitterservice;
private readonly IUploadService _uploadservice;
public STPService(ITwitterService twitterService, IUploadService uploadService)
{
_twitterservice = twitterService;
_uploadservice = uploadService;
}

public void UploadAndPost(HttpRequestBase request, string status)
{
_uploadservice.Upload(request);
_twitterservice.Update(status);
}
}
Here are my integration tests:

[TestFixture]
public class
TwitterTests
{
[Test]
public voidIsAuthenticated_user_is_authenticated_returns_false()
{
var twit = newTwitterService("baby", "badpassword");

Assert.IsFalse(twit.IsAuthenticated);
}

[Test]
public voidIsAuthenticated_user_is_authenticated_returns_true()
{
var twit = newTwitterService("baby", "password");
Assert.IsTrue(twit.IsAuthenticated);
}

[Test]
public voidIsAllowed_user_is_not_allowed_returns_false()
{
var twit = newTwitterService("baby", password");
Assert.IsFalse(twit.IsAllowed("test"));
}

[Test]
public voidIsAllowed_user_is_allowed_returns_true()
{
var twit = newTwitterService("baby", "password");
Assert.IsTrue(twit.IsAllowed("derans"));
}
}

Okay so that’s my Core & Impl now for the MVC stuff…my first real app using it…so let’s see!

I started with the default ASP.NET MVC stuff and just started modifying it. I added a method to the HomeController like this:

[AcceptVerbs(HttpVerbs.Post)]
publicActionResult Index(stringstatus)
{
var stpService = DI.CreateSTPService();
stpService.UploadAndPost(Request, status);

ViewData["UploadMessage"] = "Posted.";
returnView();
}

My Index.aspx page looks like this:

<%using(Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{ %>

<p><%=Html.Label("file", "Picture to Upload:") %><br />
<%=Html.File("file") %></p>

<
p><%=Html.Label("status", "Status:") %><br />
<%=Html.TextArea("status", "", 5, 30, null) %></p>

<
input type="submit" name="submit" value="Send" />
<%=Html.Encode(ViewData["UploadMessage"])%>

<%
} %>
I added a couple HTML Helper Extension methods in a helper file.

public static class
HtmlExtensions
{
public static stringLabel(thisHtmlHelper html, stringtarget, stringtext)
{

returnString.Format("<label for=\"{0}\">{1}</label>", target, text);
}

public static stringFile(thisHtmlHelper html, stringname)
{
returnString.Format("<input type=\"file\" name=\"{0}\" id=\"{0}\" />", name);
}
}

That’s all I got for now…as always, let me know if there is anywhere I can improve or if you have any comments. Thanks!

kick it on DotNetKicks.com

Related Posts Plugin for WordPress, Blogger...