Webservice side projects
This commit is contained in:
@@ -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
|
||||
|
0
webservice/bam/application/modules/__init__.py
Normal file
0
webservice/bam/application/modules/__init__.py
Normal file
115
webservice/bam/application/modules/admin/__init__.py
Normal file
115
webservice/bam/application/modules/admin/__init__.py
Normal 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'
|
||||
)
|
||||
|
11
webservice/bam/application/modules/admin/model.py
Normal file
11
webservice/bam/application/modules/admin/model.py
Normal 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
|
9
webservice/bam/application/modules/admin/settings.py
Normal file
9
webservice/bam/application/modules/admin/settings.py
Normal 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'))
|
17
webservice/bam/application/modules/projects/admin.py
Normal file
17
webservice/bam/application/modules/projects/admin.py
Normal 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'))
|
14
webservice/bam/application/modules/projects/model.py
Normal file
14
webservice/bam/application/modules/projects/model.py
Normal 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)
|
20
webservice/bam/application/templates/admin/layout_admin.html
Normal file
20
webservice/bam/application/templates/admin/layout_admin.html
Normal 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 %}
|
||||
#}
|
Reference in New Issue
Block a user