Webservice side projects

This commit is contained in:
2014-11-05 18:52:18 +01:00
parent aa21e8be3d
commit 073d4784df
17 changed files with 419 additions and 9 deletions

View File

@@ -27,7 +27,6 @@ if path not in sys.path:
del os, sys, path
# --------
import os
import json
import svn.local
@@ -37,12 +36,19 @@ from flask import Flask, jsonify, abort, request, make_response, url_for, Respon
from flask.views import MethodView
from flask.ext.restful import Api, Resource, reqparse, fields, marshal
from flask.ext.httpauth import HTTPBasicAuth
from flask.ext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
api = Api(app)
auth = HTTPBasicAuth()
import config
app.config.from_object(config.Development)
db = SQLAlchemy(app)
from application.modules.admin import backend
from application.modules.admin import settings
from application.modules.projects import admin
from application.modules.projects.model import Project
@auth.get_password
@@ -73,11 +79,13 @@ class DirectoryAPI(Resource):
def get(self, project_name):
project = Project.query.filter_by(name=project_name).first()
path = request.args['path']
if not path:
path = ''
absolute_path_root = app.config['STORAGE_PATH']
absolute_path_root = project.repository_path
parent_path = ''
if path != '':
@@ -134,8 +142,10 @@ class FileAPI(Resource):
filepath = request.args['filepath']
command = request.args['command']
project = Project.query.filter_by(name=project_name).first()
if command == 'info':
r = svn.local.LocalClient(app.config['STORAGE_PATH'])
r = svn.local.LocalClient(project.repository_path)
log = r.log_default(None, None, 5, filepath)
log = [l for l in log]
@@ -145,7 +155,7 @@ class FileAPI(Resource):
log=log)
elif command == 'checkout':
filepath = os.path.join(app.config['STORAGE_PATH'], filepath)
filepath = os.path.join(project.repository_path, filepath)
if not os.path.exists(filepath):
return jsonify(message="Path not found %r" % filepath)
@@ -192,6 +202,7 @@ class FileAPI(Resource):
return jsonify(message="Command unknown")
def put(self, project_name):
project = Project.query.filter_by(name=project_name).first()
command = request.args['command']
arguments = ''
if 'arguments' in request.args:
@@ -199,12 +210,12 @@ class FileAPI(Resource):
file = request.files['file']
if file and self.allowed_file(file.filename):
local_client = svn.local.LocalClient(app.config['STORAGE_PATH'])
local_client = svn.local.LocalClient(project.repository_path)
# TODO, add the merge operation to a queue. Later on, the request could stop here
# and all the next steps could be done in another loop, or triggered again via
# another request
filename = werkzeug.secure_filename(file.filename)
tmp_filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
tmp_filepath = os.path.join(project.upload_path, filename)
file.save(tmp_filepath)
# TODO, once all files are uploaded, unpack and run the tasklist (copy, add, remove

View File

@@ -0,0 +1,115 @@
from application import app, db
#from application import thumb
from flask import render_template, redirect, url_for
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext import admin, login
from flask.ext.admin import Admin, expose
from flask.ext.admin import form
from flask.ext.admin.contrib import sqla
from flask.ext.admin.contrib.sqla import ModelView
from flask.ext.admin.base import BaseView
from flask.ext.security import current_user
from werkzeug import secure_filename
from jinja2 import Markup
from wtforms import fields, validators, widgets
from wtforms.fields import SelectField, TextField
import os, hashlib, time
import os.path as op
def _list_items(view, context, model, name):
"""Utilities to upload and present images
"""
if not model.name:
return ''
return Markup(
'<div class="select2-container-multi">'
'<ul class="select2-choices" style="border:0;cursor:default;background:none;">%s</ul></div>' % (
''.join( ['<li class="select2-search-choice" style="padding:3px 5px;">'
'<div>'+item.name+'</div></li>' for item in getattr(model,name)] )))
def _list_thumbnail(view, context, model, name):
if not getattr(model,name): #model.name only does not work because name is a string
return ''
return ''
# return Markup('<img src="%s">' % url_for('static',
# filename=thumb.thumbnail(getattr(model,name), '50x50', crop='fit')))
# Create directory for file fields to use
file_path = op.join(op.dirname(__file__), '../../static/files',)
try:
os.mkdir(file_path)
except OSError:
pass
def prefix_name(obj, file_data):
# Collect name and extension
parts = op.splitext(file_data.filename)
# Get current time (for unique hash)
timestamp = str(round(time.time()))
# Has filename only (not extension)
file_name = secure_filename(timestamp + '%s' % parts[0])
# Put them together
full_name = hashlib.md5(file_name).hexdigest() + parts[1]
return full_name
def image_upload_field(label):
return form.ImageUploadField(label,
base_path=file_path,
thumbnail_size=(100, 100, True),
namegen=prefix_name,
endpoint='filemanager.static')
# Define wtforms widget and field
class CKTextAreaWidget(widgets.TextArea):
def __call__(self, field, **kwargs):
kwargs.setdefault('class_', 'ckeditor')
return super(CKTextAreaWidget, self).__call__(field, **kwargs)
class CKTextAreaField(fields.TextAreaField):
widget = CKTextAreaWidget()
# Create customized views with access restriction
class CustomModelView(ModelView):
def is_accessible(self):
return True
#return login.current_user.has_role('admin')
class CustomBaseView(BaseView):
def is_accessible(self):
return True
#return login.current_user.has_role('admin')
# Create customized index view class that handles login & registration
class CustomAdminIndexView(admin.AdminIndexView):
def is_accessible(self):
return True
#return login.current_user.has_role('admin')
@expose('/')
def index(self):
return super(CustomAdminIndexView, self).index()
@expose('/logout/')
def logout_view(self):
login.logout_user()
return redirect(url_for('homepage'))
# Create admin
backend = Admin(
app,
'BAM',
index_view=CustomAdminIndexView(),
base_template='admin/layout_admin.html'
)

View File

@@ -0,0 +1,11 @@
from application import db
class Setting(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(256), unique=True, nullable=False)
description = db.Column(db.Text)
value = db.Column(db.String(100), nullable=False)
data_type = db.Column(db.String(128), nullable=False)
def __unicode__(self):
return self.name

View File

@@ -0,0 +1,9 @@
from application import app
from application import db
from application.modules.admin.model import Setting
from application.modules.admin import *
# Add views
backend.add_view(CustomModelView(Setting, db.session, name='Settings', url='settings'))

View File

@@ -0,0 +1,17 @@
from application import app
from application import db
from application.modules.projects.model import Project
from application.modules.admin import *
from application.modules.admin import _list_thumbnail
class ProjectView(CustomModelView):
column_searchable_list = ('name',)
column_list = ('name', 'picture', 'creation_date')
#column_formatters = { 'picture': _list_thumbnail }
#form_extra_fields = {'picture': image_upload_field('Header')}
# Add views
backend.add_view(ProjectView(Project, db.session, name='Projects', url='projects'))

View File

@@ -0,0 +1,14 @@
import datetime
from application import db
class Project(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(255), nullable=False)
repository_path = db.Column(db.Text, nullable=False)
upload_path = db.Column(db.Text, nullable=False)
picture = db.Column(db.String(80))
creation_date = db.Column(db.DateTime(), default=datetime.datetime.now)
status = db.Column(db.String(80)) #pending #active #inactive
def __str__(self):
return str(self.name)

View File

@@ -0,0 +1,20 @@
{% extends 'admin/base.html' %}
{% block brand %}
<span class="brand"><a href="#">{{ admin_view.admin.name }}</a></span>
{% endblock %}
{#
{% block access_control %}
{% if current_user.is_authenticated() %}
<div class="btn-group pull-right">
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
<i class="icon-user"></i> {{ current_user.login }} <span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li><a href="{{ url_for('admin.logout_view') }}">Log out</a></li>
</ul>
</div>
{% endif %}
{% endblock %}
#}