]> git.frykholm.com Git - friends.git/blob - friends/server.py
Some more cleanup, storing secret for use with hashlib.hmac
[friends.git] / friends / server.py
1 import tornado.ioloop
2 import tornado.web
3 import os, os.path
4 import tornado.httpserver
5 import sqlite3
6 import arrow
7 import datetime
8 from rd import RD, Link
9 import hashlib
10 db = None
11 #insert into user (name,email) values('mikael','mikael@frykholm.com');
12 #insert into entry (userid,text) values (1,'My thoughts on ostatus');
13 import tornado.options
14
15 settings = {
16 "static_path": os.path.join(os.path.dirname(__file__), "static"),
17 "cookie_secret": "__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__",
18 "login_url": "/login",
19 "xsrf_cookies": False,
20 "domain":"https://ronin.frykholm.com",
21
22 }
23 class PushHandler(tornado.web.RequestHandler):
24 #curl -v -k "https://ronin.frykholm.com/hub" -d "hub.callback=a" -d "hub.mode=b" -d "hub.topic=c" -d "hub.verify=d"
25 def post(self):
26 """ Someone wants to subscribe to hub_topic feed"""
27 hub_callback = self.get_argument('hub.callback')
28 hub_mode = self.get_argument('hub.mode')
29 hub_topic = self.get_argument('hub.topic')
30 hub_verify = self.get_argument('hub.verify')
31 hub_lease_seconds = self.get_argument('hub.lease_seconds','')
32 hub_secret = self.get_argument('hub.sercret','')
33 hub_verify_token = self.get_argument('hub.verify_token','')
34 print(self.request.body)
35 if hub_mode == 'unsubscribe':
36 pass #FIXME
37 path = hub_topic.split(self.settings['domain'])[1]
38 user = path.split('user/')[1]
39 row = db.execute("select id from user where name=?",(user,)).fetchone()
40 if row: #FIXME calculate expire timestamp
41 db.execute("INSERT into subscriptions (userid, expires, callback, secret, verified) values (?,?,?,?)",(row['id'],datetime.datetime.now(),hub_secret,hub_callback,False))
42 db.commit()
43 self.set_status(202)
44 #TODO add GET callback with the same data we got
45 #TODO add secret to outgoing feeds with hmac
46
47 class XrdHandler(tornado.web.RequestHandler):
48 def get(self):
49 self.render("templates/xrd.xml", hostname="ronin.frykholm.com", url=self.settings['domain'])
50
51 class FingerHandler(tornado.web.RequestHandler):
52 def get(self):
53 user = self.get_argument('resource')
54 user = user.split('acct:')[1]
55 (user,domain) = user.split('@')
56 rows = db.execute("select id from user where user.name=?",(user,)).fetchone()
57 if not rows:
58 self.set_status(404)
59 self.write("Not found")
60 self.finish()
61 return
62 lnk = Link(rel='http://spec.example.net/photo/1.0',
63 type='image/jpeg',
64 href='{}/static/{}.jpg'.format(self.settings['domain'],user))
65 lnk.titles.append(('User Photo', 'en'))
66 lnk.titles.append(('Benutzerfoto', 'de'))
67 lnk.properties.append(('http://spec.example.net/created/1.0', '1970-01-01'))
68 lnk2 = Link(rel='http://schemas.google.com/g/2010#updates-from',
69 type='application/atom+xml',
70 href='{}/user/{}'.format(self.settings['domain'],user))
71
72 rd = RD(subject='{}/{}'.format(self.settings['domain'],user))
73 rd.properties.append('http://spec.example.net/type/person')
74 rd.links.append(lnk)
75 rd.links.append(lnk2)
76 self.write(rd.to_json())
77
78 class UserHandler(tornado.web.RequestHandler):
79 def get(self, user):
80 entries = db.execute("select entry.id,text,ts from user,entry where user.id=entry.userid and user.name=?",(user,))
81 #import pdb;pdb.set_trace()
82 self.set_header("Content-Type", 'application/atom+xml')
83 self.render("templates/feed.xml",
84 user=user,
85 feed_url="{}/user/{}".format(self.settings['domain'], user),
86 hub_url="{}/hub".format(self.settings['domain']),
87 entries=entries,
88 arrow=arrow )
89
90 application = tornado.web.Application([
91 (r"/.well-known/host-meta", XrdHandler),
92 (r"/.well-known/webfinger", FingerHandler),
93 (r"/user/(.+)", UserHandler),
94 (r"/hub", PushHandler),
95 ],debug=True,**settings)
96 srv = tornado.httpserver.HTTPServer(application, ssl_options={
97 "certfile": "ronin.frykholm.com.pem",
98 "keyfile": "ronin.frykholm.com.key",
99 })
100 def setup_db(path):
101 print("No db found, creating in {}".format(path))
102 con = sqlite3.connect(path)
103 con.execute(""" create table user (id integer primary key,
104 name varchar,
105 email varchar);
106 create table entry (id integer primary key,
107 userid INTEGER,
108 text varchar,
109 ts timestamp default current_timestamp,
110 FOREIGN KEY(userid) REFERENCES user(id));
111 create table subscriptions (id integer primary key,
112 userid integer,
113 expires datetime,
114 callback varchar,
115 secret varchar,
116 verified bool,
117 FOREIGN KEY(userid) REFERENCES user(id));""")
118 con.commit()
119
120 if __name__ == "__main__":
121 dbPath = 'friends.db'
122 tornado.options.parse_command_line()
123 if not os.path.exists(dbPath):
124 setup_db(dbPath)
125 db = sqlite3.connect(dbPath, detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
126 db.row_factory = sqlite3.Row
127 srv.listen(443)
128 tornado.ioloop.IOLoop.instance().start()