3579442 by Anon Ray at 2013-05-03 1
#!/usr/bin/python
63c7919 by Anon Ray at 2013-05-30 2
4a1fae7 by Anon Ray at 2013-05-09 3
# Mouchak Server -
4
# A Flask Application (http://flask.pocoo.org/)
5
3579442 by Anon Ray at 2013-05-03 6
import flask
4a1fae7 by Anon Ray at 2013-05-09 7
import pymongo
8
import bson
668b408 by Anon Ray at 2013-07-01 9
import conf
4e1af81 by Anon Ray at 2013-10-07 10
import os
11
from werkzeug import secure_filename
12
13
PLUGIN_UPLOAD_FOLDER = os.path.join(os.path.dirname(os.path.abspath(__file__))
14
                                    + '/static/user_plugins')
15
PLUGIN_ALLOWED_EXTENSIONS = set(['js', 'css'])
16
17
FILE_UPLOAD_FOLDER = os.path.join(os.path.dirname(os.path.abspath(__file__)) +
18
                                  '/static/uploads')
3579442 by Anon Ray at 2013-05-03 19
20
app = flask.Flask(__name__)
21
63c7919 by Anon Ray at 2013-05-30 22
23
4a1fae7 by Anon Ray at 2013-05-09 24
dbClient = pymongo.MongoClient()
668b408 by Anon Ray at 2013-07-01 25
db = dbClient[conf.DB]
63c7919 by Anon Ray at 2013-05-30 26
siteContent = db['content']
27
siteMenu = db['menu']
28
if siteMenu.find_one() == None:
2bded2d by Anon Ray at 2013-09-11 29
    siteMenu.insert({'customMenu': False, 'menuOrder': [], 'html': ''})
3fd837c by Anon Ray at 2013-08-23 30
63c7919 by Anon Ray at 2013-05-30 31
4a1fae7 by Anon Ray at 2013-05-09 32
# handy reference to otherwise long name
33
bson.ObjId = bson.objectid.ObjectId
34
63c7919 by Anon Ray at 2013-05-30 35
4a1fae7 by Anon Ray at 2013-05-09 36
def getContent():
37
    content = []
63c7919 by Anon Ray at 2013-05-30 38
    for i in siteContent.find():
4a1fae7 by Anon Ray at 2013-05-09 39
        objId = bson.ObjId(i['_id'])
40
        del(i['_id'])
41
        i['id'] = str(objId)
42
        content.append(i)
63c7919 by Anon Ray at 2013-05-30 43
44
    menu = siteMenu.find_one()
45
    objId = bson.ObjId(menu['_id'])
46
    del(menu['_id'])
47
    menu['id'] = str(objId)
48
49
    return {'content': content, 'menu': menu}
50
4a1fae7 by Anon Ray at 2013-05-09 51
4e1af81 by Anon Ray at 2013-10-07 52
def allowed_file(filename):
53
    return '.' in filename and \
54
            filename.rsplit('.', 1)[1] in PLUGIN_ALLOWED_EXTENSIONS
55
56
bf40f62 by Anon Ray at 2013-10-06 57
@app.errorhandler(404)
58
def pageNotFound(e):
59
    return flask.render_template('404.html'), 404
60
4a1fae7 by Anon Ray at 2013-05-09 61
3579442 by Anon Ray at 2013-05-03 62
@app.route('/', methods=['GET'])
63
def index():
63c7919 by Anon Ray at 2013-05-30 64
    return flask.render_template('index.html', content=getContent(),
7a60100 by Anon Ray at 2013-08-23 65
                                 title=conf.SITE_TITLE, footer=conf.SITE_FOOTER)
4a1fae7 by Anon Ray at 2013-05-09 66
67
63c7919 by Anon Ray at 2013-05-30 68
@app.route('/edit', methods=['GET'])
4a1fae7 by Anon Ray at 2013-05-09 69
def edit():
bb07f56 by Anon Ray at 2013-09-06 70
    if "logged_in" in flask.session:
71
        flask.session['key'] = conf.SECRET_KEY
72
        return flask.render_template('editor.html', content=getContent(),
73
                                     title=conf.SITE_TITLE)
74
    else:
75
        return flask.redirect(flask.url_for('login'))
4a1fae7 by Anon Ray at 2013-05-09 76
77
63c7919 by Anon Ray at 2013-05-30 78
@app.route('/page', methods=['POST'])
79
def insertPage():
80
    newpage = flask.request.json
81
    print newpage
82
    res = siteContent.insert(newpage)
83
    _id = bson.ObjId(res)
84
    newpage['id'] = str(_id)
85
    del(newpage['_id'])
86
    print newpage
87
    # FIXME: handle errors
24cd97e by Anon Ray at 2013-10-06 88
    #return flask.jsonify(status='ok', page=newpage)
89
    return flask.jsonify(newpage)
63c7919 by Anon Ray at 2013-05-30 90
91
92
@app.route('/page/<_id>', methods=['PUT', 'DELETE'])
93
def updatePage(_id):
4a1fae7 by Anon Ray at 2013-05-09 94
    if flask.request.method == 'PUT':
95
        changedPage = flask.request.json
96
        print changedPage
63c7919 by Anon Ray at 2013-05-30 97
        print '======='
98
        res = siteContent.update({'_id': bson.ObjId(_id)},
4a1fae7 by Anon Ray at 2013-05-09 99
                                changedPage)
100
        print res
63c7919 by Anon Ray at 2013-05-30 101
        if res['err'] == None:
102
            print changedPage
24cd97e by Anon Ray at 2013-10-06 103
            #return flask.jsonify(status='ok', page=changedPage)
104
            return flask.jsonify(changedPage)
4a1fae7 by Anon Ray at 2013-05-09 105
106
    elif flask.request.method == 'DELETE':
107
        delPage = flask.request.url
108
        print delPage
109
        print _id
63c7919 by Anon Ray at 2013-05-30 110
        res = siteContent.remove({'_id': bson.ObjId(_id)})
4a1fae7 by Anon Ray at 2013-05-09 111
        print res
63c7919 by Anon Ray at 2013-05-30 112
        if res['err'] == None:
113
            return flask.jsonify(status='ok')
114
        else:
115
            return flask.jsonify(error=res['err'], status='error')
4a1fae7 by Anon Ray at 2013-05-09 116
3579442 by Anon Ray at 2013-05-03 117
40ce989 by Anon Ray at 2013-09-07 118
@app.route('/menu', methods=['POST'])
119
def insertMenu():
120
    #newmenu = flask.request.json
121
    #print newmenu
122
    #res = siteMenu.insert(newmenu)
123
    #print res
124
    #return flask.jsonify(status='success')#, content=getContent())
125
    return '200 OK'
126
4a1fae7 by Anon Ray at 2013-05-09 127
63c7919 by Anon Ray at 2013-05-30 128
@app.route('/menu/<_id>', methods=['PUT'])
129
def updateMenu(_id):
130
    if flask.request.method == 'PUT':
131
        changedMenu = flask.request.json
bb07f56 by Anon Ray at 2013-09-06 132
        print "changed menu:"
63c7919 by Anon Ray at 2013-05-30 133
        print changedMenu
134
        res = siteMenu.update({'_id': bson.ObjId(_id)}, changedMenu)
135
        print res
24cd97e by Anon Ray at 2013-10-06 136
        #return flask.jsonify(status='ok', menu=changedMenu)
137
        return flask.jsonify(changedMenu)
63c7919 by Anon Ray at 2013-05-30 138
139
    #elif flask.request.method == 'DELETE':
140
    #    delMenu = flask.request.url
141
    #    print delMenu
142
    #    print _id
143
    #    res = siteMenu.remove({'_id': bson.ObjId(_id)})
144
    #    return flask.jsonify(status='deleted')
145
146
bb07f56 by Anon Ray at 2013-09-06 147
# Basic login for one single admin user whose credentials are in conf.py
148
@app.route('/login', methods=['GET', 'POST'])
149
def login():
150
    error = None
151
    if flask.request.method == 'POST':
152
        print flask.request.form
153
        if flask.request.form['username'] != conf.ADMIN_USERNAME:
154
            error = 'Invalid username'
155
        elif flask.request.form['password'] != conf.ADMIN_PASSWORD:
156
            error = 'Invaid password'
157
        else:
158
            flask.session['logged_in'] = True
159
            flask.session['key'] = conf.SECRET_KEY
160
            flask.flash('You were logged in')
161
            return flask.redirect(flask.url_for('edit'))
162
    return flask.render_template('login.html', error=error)
163
164
@app.route('/logout')
165
def logout():
166
    flask.session.pop('logged_in', None)
167
    flask.flash('You were logged out')
168
    return flask.redirect(flask.url_for('login'))
169
4e1af81 by Anon Ray at 2013-10-07 170
171
#TODO: refactor these code to classes
172
#TODO: find out if this is a good method for saving plugins..
173
@app.route('/static/user_plugins/<filename>', methods=['POST'])
174
def savePlugin(filename):
175
    if flask.request.method == 'POST':
176
        if filename and allowed_file(filename):
177
            data = flask.request.form['code']
178
            filename = secure_filename(filename)
179
            fh = open(os.path.join(PLUGIN_UPLOAD_FOLDER + '/' + filename), 'w')
180
            fh.write(data)
181
            fh.close()
182
            return flask.jsonify(saved = True)
183
184
#TODO: find out if this is a good method for uploading plugins..
185
@app.route('/upload/plugin', methods=['POST'])
186
def uploadPlugin():
187
    if flask.request.method == 'POST':
188
        print flask.request.files
189
        file = flask.request.files['plugin-file']
190
        if file and allowed_file(file.filename):
191
            filename = secure_filename(file.filename)
192
            file.save(os.path.join(app.config['PLUGIN_UPLOAD_FOLDER'],
193
                                   filename))
194
195
            #return flask.redirect(flask.url_for('uploaded_file',
196
            #            filename=filename))
197
            return flask.jsonify(uploaded = True,
198
                                 path=flask.url_for('static', filename =
199
                                                    'user_plugins/'+ filename))
200
bb07f56 by Anon Ray at 2013-09-06 201
@app.route('/robots.txt')
202
@app.route('/crossdomain.xml')
203
def static_from_root():
204
    return flask.send_from_directory(app.static_folder, request.path[1:])
205
206
207
app.config.from_object(conf)
4e1af81 by Anon Ray at 2013-10-07 208
app.config['PLUGIN_UPLOAD_FOLDER'] = PLUGIN_UPLOAD_FOLDER
3fd837c by Anon Ray at 2013-08-23 209
2768342 by Anon Ray at 2013-09-06 210
import logging,os
211
from logging import FileHandler
212
213
fil = FileHandler(os.path.join(os.path.dirname(__file__),'logme'),mode='a')
214
fil.setLevel(logging.ERROR)
215
app.logger.addHandler(fil)
216
217
218
63c7919 by Anon Ray at 2013-05-30 219
if __name__ == "__main__":
c94d3ad by Anon Ray at 2013-07-01 220
    app.run(debug=True, host=conf.HOST, port=conf.PORT)
668b408 by Anon Ray at 2013-07-01 221