Commit 5c764bdb authored by buttle's avatar buttle

Added change author

parent 640503c9
...@@ -31,8 +31,8 @@ babel = Babel(app) ...@@ -31,8 +31,8 @@ babel = Babel(app)
csrf = CSRFProtect() csrf = CSRFProtect()
csrf.init_app(app) csrf.init_app(app)
app.config['APP_VERSION'] = 28 app.config['APP_VERSION'] = 29
app.config['SCHEMA_VERSION'] = 12 app.config['SCHEMA_VERSION'] = 13
app.config['RESERVED_SLUGS'] = ['static', 'admin', 'admins', 'user', 'users', 'form', 'forms', 'site', 'sites', 'update'] app.config['RESERVED_SLUGS'] = ['static', 'admin', 'admins', 'user', 'users', 'form', 'forms', 'site', 'sites', 'update']
# DPL = Data Protection Law # DPL = Data Protection Law
......
...@@ -22,6 +22,7 @@ from flask_babel import gettext ...@@ -22,6 +22,7 @@ from flask_babel import gettext
from GNGforms import app from GNGforms import app
from GNGforms.persistence import Site from GNGforms.persistence import Site
import smtplib, socket import smtplib, socket
from threading import Thread
def createSmtpObj(): def createSmtpObj():
config=g.site.data["smtpConfig"] config=g.site.data["smtpConfig"]
......
...@@ -150,5 +150,11 @@ def migrateMongoSchema(schemaVersion): ...@@ -150,5 +150,11 @@ def migrateMongoSchema(schemaVersion):
mongo.db.forms.update_one({"_id": form["_id"]}, {"$set": {"restrictedAccess": False}}) mongo.db.forms.update_one({"_id": form["_id"]}, {"$set": {"restrictedAccess": False}})
schemaVersion=12 schemaVersion=12
if schemaVersion == 12:
# Add admin prefs. to forms
for form in mongo.db.forms.find():
mongo.db.forms.update_one({"_id": form["_id"]}, {"$set": {"adminPreferences": { "public": True }}})
schemaVersion=13
# this can't be a good migration setup :( # this can't be a good migration setup :(
return schemaVersion return schemaVersion
...@@ -194,7 +194,8 @@ class User(object): ...@@ -194,7 +194,8 @@ class User(object):
@property @property
def forms(self): def forms(self):
return Form().findAll(editor=str(self._id)) #return Form().findAll(editor=str(self._id))
return [Form(_id=form['_id']) for form in Form().findAll(editor=str(self._id))]
@property @property
def admin(self): def admin(self):
...@@ -340,7 +341,21 @@ class Form(object): ...@@ -340,7 +341,21 @@ class Form(object):
@property @property
def author(self): def author(self):
return self.form['author'] return self.form['author']
@author.setter
def author(self, value):
self.form["author"]=value
def changeAuthor(self, new_author):
if new_author.enabled:
if self.author in self.editors:
del self.editors[self.author]
self.author=str(new_author._id)
if self.addEditor(new_author):
self.save()
return True
return False
@property @property
def user(self): def user(self):
return User(_id=self.form['author']) return User(_id=self.form['author'])
...@@ -393,15 +408,22 @@ class Form(object): ...@@ -393,15 +408,22 @@ class Form(object):
@property @property
def enabled(self): def enabled(self):
if not self.form['adminPreferences']['public']:
return False
return self.form['enabled'] return self.form['enabled']
def newEditorPreferences(cls): def newEditorPreferences(cls):
return {'notification': {'newEntry': False, 'expiredForm': True}} return {'notification': {'newEntry': False, 'expiredForm': True}}
def addEditor(self, editor_id): def addEditor(self, editor):
if not editor.enabled:
return False
editor_id=str(editor._id)
if not editor_id in self.form['editors']: if not editor_id in self.form['editors']:
self.form['editors'][editor_id]=Form().newEditorPreferences() self.form['editors'][editor_id]=Form().newEditorPreferences()
mongo.db.forms.update_one({'_id': self.form['_id']}, {"$set": {"editors": self.form['editors']}}) mongo.db.forms.update_one({'_id': self.form['_id']}, {"$set": {"editors": self.form['editors']}})
return True
return False
def removeEditor(self, editor_id): def removeEditor(self, editor_id):
if editor_id == self.author: if editor_id == self.author:
...@@ -569,13 +591,18 @@ class Form(object): ...@@ -569,13 +591,18 @@ class Form(object):
return "%s/%s/%s" % (self.url, part, self.form['sharedEntries']['key']) return "%s/%s/%s" % (self.url, part, self.form['sharedEntries']['key'])
def toggleEnabled(self): def toggleEnabled(self):
if self.expired: if self.expired or self.form['adminPreferences']['public']==False:
return False return False
else: else:
self.form['enabled'] = False if self.form['enabled'] else True self.form['enabled'] = False if self.form['enabled'] else True
mongo.db.forms.save(self.form) mongo.db.forms.save(self.form)
return self.form['enabled'] return self.form['enabled']
def toggleAdminFormPublic(self):
self.form['adminPreferences']['public'] = False if self.form['adminPreferences']['public'] else True
mongo.db.forms.save(self.form)
return self.form['adminPreferences']['public']
def toggleSharedEntries(self): def toggleSharedEntries(self):
self.form['sharedEntries']['enabled'] = False if self.form['sharedEntries']['enabled'] else True self.form['sharedEntries']['enabled'] = False if self.form['sharedEntries']['enabled'] else True
mongo.db.forms.save(self.form) mongo.db.forms.save(self.form)
......
{% extends "base.html" %}
{% block content %}
<div class="container">
<div class="row col-md-3"></div>
<div class="row col-md-7" style="font-size:1.5em">
<input class="btn-primary btn btn-sm" type="button" value="{%trans%}Return to form{%endtrans%}" onClick="location.href='/forms/view/{{ form._id }}'">
{{ form.slug }}
<hr />
</div>
<div class="row col-md-2"></div>
</div>
<div class="container">
<div class="row col-md-3"></div>
<div class="row col-md-5">
<div style="font-size:1.5em; padding-bottom:1em;">
{%trans%}Change author{%endtrans%}
</div>
<table class="table table-striped table-condensed">
<tr>
<td>{%trans%}Current author{%endtrans%}</td>
<td>{{ form.user.username }}</td>
</tr>
</table>
{%trans%}You are going to change the author of this form.{%endtrans%}<br />
{%trans%}Are you sure?{%endtrans%}
<p>&nbsp;</p>
<form action="/admin/forms/change-author/{{form._id}}" method="POST">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input name="new_author_username" type="text" placeholder="{%trans%}New author's username{%endtrans%}" class="form-control" required />
<p></p>
<input class="btn-primary btn btn-md" type="submit" value="{%trans%}Change author{%endtrans%}" />
</form>
{% if editors|length > 1 %}
<p>&nbsp;</p>
<div style="font-size:1.5em;">
{%trans%}Editors{%endtrans%}
</div>
<div>
{%trans%}Users listed here have the <b>same permissions</b> as the author{%endtrans%}
</div>
<p style="padding-top:1.2em;"></p>
<table class="table table-condensed">
{% for editor in editors %}
<tr id="editor_{{editor._id}}">
<td>{{ editor.username }}</td>
<td>{{ editor.email }}</td>
<td class="text-right">
{% if editor._id|string == form.author %}
({%trans%}Author{%endtrans%})
{% else %}
<input class="btn btn-xs btn-danger" type="button" value="{%trans%}Remove{%endtrans%}" onClick="js:removeEditor('{{editor._id}}');">
{% endif %}
</td>
</tr>
{% endfor %}
</table>
{% endif %}
</div>
<div class="row col-md-4"></div>
</div>
<script>
var csrftoken = "{{ csrf_token() }}";
function removeEditor(editor_id){
$.ajax({
url : "/forms/remove-editor/{{form._id}}/"+editor_id,
type: "POST",
dataType: "json",
beforeSend: function(xhr, settings) {
if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type)) {
xhr.setRequestHeader("X-CSRFToken", csrftoken)
}
},
success: function(data, textStatus, jqXHR)
{
if (data == editor_id) {
$('#editor_'+editor_id).hide();
}
}
});
}
</script>
{% endblock %}
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
{%trans%}Delete user{%endtrans%} {%trans%}Delete user{%endtrans%}
</div> </div>
<hr /> <hr />
{% set formCount=user.forms.count() %} {% set formCount=user.forms|length %}
{%trans%}You are going to delete a user{%endtrans%} {%trans%}You are going to delete a user{%endtrans%}
{% if formCount %} {% if formCount %}
{%trans%}and their forms{%endtrans%} {%trans%}and their forms{%endtrans%}
......
...@@ -55,7 +55,7 @@ ...@@ -55,7 +55,7 @@
</td> </td>
</tr> </tr>
<tr> <tr>
<td>{%trans%}Published{%endtrans%}</td> <td>{%trans%}Public{%endtrans%}</td>
<td> <td>
{% if form.editors[g.current_user._id|string] is defined %} {% if form.editors[g.current_user._id|string] is defined %}
<div id="toggle_enabled" class="btn-group btn-toggle"> <div id="toggle_enabled" class="btn-group btn-toggle">
...@@ -63,10 +63,7 @@ ...@@ -63,10 +63,7 @@
<button id="enabled_false" class="btn btn-xs btn-default {% if not form.isPublic() %}btn-primary{% endif %}">{%trans%}False{%endtrans%}</button> <button id="enabled_false" class="btn btn-xs btn-default {% if not form.isPublic() %}btn-primary{% endif %}">{%trans%}False{%endtrans%}</button>
</div> </div>
{% else %} {% else %}
{{ form.isPublic() }} {{ form.isPublic() }}
{% if not form.user.enabled %}
<span style="color:red">({%trans%}user disabled{%endtrans%})</span>
{% endif %}
{% endif %} {% endif %}
</td> </td>
</tr> </tr>
...@@ -93,7 +90,12 @@ ...@@ -93,7 +90,12 @@
</td> </td>
</tr> </tr>
<tr> <tr>
<td>{%trans%}Public URL{%endtrans%}</td> <td>
{%trans%}Public URL{%endtrans%}
{% if not form.data['adminPreferences']['public'] %}
<span style="color:red">({%trans%}disabled{%endtrans%})</span>
{% endif %}
</td>
<td> <td>
{% if form.isPublic() %} {% if form.isPublic() %}
<a id="formLink" href="{{ form.url }}">{{ form.url }}</a> <a id="formLink" href="{{ form.url }}">{{ form.url }}</a>
...@@ -148,12 +150,19 @@ ...@@ -148,12 +150,19 @@
</tr> </tr>
{% endif %} {% endif %}
<tr> <tr>
<td>{%trans%}Author{%endtrans%}</td> <td>
{%trans%}Author{%endtrans%}
{% if not form.user.enabled %}
<span style="color:red">({%trans%}disabled{%endtrans%})</span>
{% endif %}
</td>
<td>
{% if g.isAdmin %} {% if g.isAdmin %}
<td><a href="/admin/users/{{ form.user._id }}">{{ form.user.username }}</a></td> <a href="/admin/users/{{ form.user._id }}">{{ form.user.username }}</a>
{% else %} {% else %}
<td>{{ form.user.username }}</td> {{ form.user.username }}
{% endif %} {% endif %}
</td>
</tr> </tr>
<tr> <tr>
<td>{%trans%}Created{%endtrans%}</td> <td>{%trans%}Created{%endtrans%}</td>
...@@ -178,6 +187,19 @@ ...@@ -178,6 +187,19 @@
<input class="btn-danger btn btn-sm" type="button" value="{%trans%}Delete form and entries{%endtrans%}" onClick="location.href='/forms/delete/{{ form._id }}'"> <input class="btn-danger btn btn-sm" type="button" value="{%trans%}Delete form and entries{%endtrans%}" onClick="location.href='/forms/delete/{{ form._id }}'">
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if g.isAdmin %}
<div style="font-size:1.5em; padding-top:1em;">
{%trans%}Admin options{%endtrans%}
</div>
<hr />
<input class="btn-primary btn btn-sm" type="button" value="{%trans%}Change author{%endtrans%}" onClick="location.href='/admin/forms/change-author/{{form._id}}'" >
{% if form.data['adminPreferences']['public'] %}
<input class="btn-danger btn btn-sm" type="button" value="{%trans%}Disable form{%endtrans%}" onClick="location.href='/admin/forms/toggle-public/{{form._id}}'" >
{% else %}
<input class="btn-primary btn btn-sm" type="button" value="{%trans%}Enable form{%endtrans%}" onClick="location.href='/admin/forms/toggle-public/{{form._id}}'" >
{% endif %}
{% endif %}
</div> </div>
</div> </div>
......
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
<tr> <tr>
<td>{%trans%}Validated email{%endtrans%}</td> <td>{%trans%}Validated email{%endtrans%}</td>
<td> {% if user.data.validatedEmail %} <td> {% if user.data.validatedEmail %}
<span style="color:green">{%trans%}True{%endtrans%}</span> <span>{%trans%}True{%endtrans%}</span>
{% else %} {% else %}
<span style="color:red">{%trans%}False{%endtrans%}</span> <span style="color:red">{%trans%}False{%endtrans%}</span>
{% endif %} {% endif %}
...@@ -65,7 +65,7 @@ ...@@ -65,7 +65,7 @@
</tr> </tr>
</table> </table>
{% if g.isAdmin and not user._id == g.current_user._id %} {% if g.isAdmin and not user._id == g.current_user._id %}
{% if user.forms.count() %} {% if user.forms|length %}
<input class="btn-danger btn btn-sm" type="button" value="{%trans%}Delete user and authored forms{%endtrans%}" onClick="location.href='/admin/users/delete/{{user._id}}'"> <input class="btn-danger btn btn-sm" type="button" value="{%trans%}Delete user and authored forms{%endtrans%}" onClick="location.href='/admin/users/delete/{{user._id}}'">
{% else %} {% else %}
<input class="btn-danger btn btn-sm" type="button" value="{%trans%}Delete user{%endtrans%}" onClick="location.href='/admin/users/delete/{{user._id}}'"> <input class="btn-danger btn btn-sm" type="button" value="{%trans%}Delete user{%endtrans%}" onClick="location.href='/admin/users/delete/{{user._id}}'">
...@@ -87,7 +87,7 @@ ...@@ -87,7 +87,7 @@
<th>{%trans%}Created{%endtrans%}</th> <th>{%trans%}Created{%endtrans%}</th>
<th>{%trans%}Author{%endtrans%}</th> <th>{%trans%}Author{%endtrans%}</th>
<th>{%trans%}Editors{%endtrans%}</th> <th>{%trans%}Editors{%endtrans%}</th>
<th>{%trans%}Enabled{%endtrans%}</th> <th>{%trans%}Public{%endtrans%}</th>
<th>{%trans%}Entries{%endtrans%}</th> <th>{%trans%}Entries{%endtrans%}</th>
</tr> </tr>
</thead> </thead>
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
<td>{{user.data.created}}</td> <td>{{user.data.created}}</td>
<td>{{user.enabled}}</td> <td>{{user.enabled}}</td>
<td>{{user.email}}</td> <td>{{user.email}}</td>
<td>{{user.forms.count()}}</td> <td>{{user.forms|length}}</td>
<td>{{user.isAdmin()}}</td> <td>{{user.isAdmin()}}</td>
</tr> </tr>
{% endfor %} {% endfor %}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -24,9 +24,9 @@ from GNGforms import app, mongo, babel ...@@ -24,9 +24,9 @@ from GNGforms import app, mongo, babel
from threading import Thread from threading import Thread
from flask_babel import gettext, refresh from flask_babel import gettext, refresh
from GNGforms.persistence import * from GNGforms.persistence import *
from .session import * from GNGforms.session import *
from .utils import * from GNGforms.utils import *
from .email import * from GNGforms.email import *
from form_templates import formTemplates from form_templates import formTemplates
import pprint import pprint
...@@ -275,17 +275,17 @@ def add_editor(_id): ...@@ -275,17 +275,17 @@ def add_editor(_id):
if not isValidEmail(request.form['email']): if not isValidEmail(request.form['email']):
return redirect(make_url_for('share_form', _id=queriedForm._id)) return redirect(make_url_for('share_form', _id=queriedForm._id))
newEditor=User(hostname=g.site.hostname, email=request.form['email'], validatedEmail=True) newEditor=User(hostname=g.site.hostname, email=request.form['email'])
if not newEditor: if not newEditor or newEditor.enabled==False:
flash(gettext("Can't find a user with that email"), 'warning') flash(gettext("Can't find a user with that email"), 'warning')
return redirect(make_url_for('share_form', _id=queriedForm._id)) return redirect(make_url_for('share_form', _id=queriedForm._id))
if str(newEditor._id) in queriedForm.editors: if str(newEditor._id) in queriedForm.editors:
flash(gettext("%s is already an editor" % newEditor.email), 'warning') flash(gettext("%s is already an editor" % newEditor.email), 'warning')
return redirect(make_url_for('share_form', _id=queriedForm._id)) return redirect(make_url_for('share_form', _id=queriedForm._id))
queriedForm.addEditor(str(newEditor._id)) if queriedForm.addEditor(newEditor):
flash(gettext("New editor added ok"), 'success') flash(gettext("New editor added ok"), 'success')
queriedForm.addLog(gettext("Added editor %s" % newEditor.email)) queriedForm.addLog(gettext("Added editor %s" % newEditor.email))
return redirect(make_url_for('share_form', _id=queriedForm._id)) return redirect(make_url_for('share_form', _id=queriedForm._id))
...@@ -530,7 +530,8 @@ def save_form(_id=None): ...@@ -530,7 +530,8 @@ def save_form(_id=None):
"afterSubmitText": afterSubmitText, "afterSubmitText": afterSubmitText,
"log": [], "log": [],
"requireDataConsent": g.site.isPersonalDataConsentEnabled(), "requireDataConsent": g.site.isPersonalDataConsentEnabled(),
"restrictedAccess": False "restrictedAccess": False,
"adminPreferences": { "public": True }
} }
newForm=Form().insert(newFormData) newForm=Form().insert(newFormData)
clearSessionFormData() clearSessionFormData()
...@@ -901,14 +902,11 @@ def new_user(token=None): ...@@ -901,14 +902,11 @@ def new_user(token=None):
if not user: if not user:
flash(gettext("Opps! An error ocurred when creating the user"), 'error') flash(gettext("Opps! An error ocurred when creating the user"), 'error')
return render_template('new-user.html') return render_template('new-user.html')
if invite: if invite:
invite.delete() invite.delete()
@after_this_request thread = Thread(target=smtpSendNewUserNotification(User().getNotifyNewUserEmails(), user.username))
def send_newuser_email(response): thread.start()
smtpSendNewUserNotification(User().getNotifyNewUserEmails(), user.username)
return response
if validatedEmail == True: if validatedEmail == True:
# login an invited user # login an invited user
...@@ -1377,7 +1375,40 @@ def list_forms(): ...@@ -1377,7 +1375,40 @@ def list_forms():
forms = [Form(_id=form['_id']) for form in Form().findAll()] forms = [Form(_id=form['_id']) for form in Form().findAll()]
return render_template('list-forms.html', forms=forms) return render_template('list-forms.html', forms=forms)
@app.route('/admin/forms/toggle-public/<string:_id>', methods=['GET'])
@admin_required
def toggle_form_public_admin_prefs(_id):
queriedForm = Form(_id=_id)
if not queriedForm:
flash(gettext("Can't find that form"), 'warning')
return redirect(make_url_for('my_forms'))
queriedForm.toggleAdminFormPublic()
return redirect(make_url_for('inspect_form', _id=_id))
@app.route('/admin/forms/change-author/<string:_id>', methods=['GET', 'POST'])
@admin_required
def change_author(_id):
queriedForm = Form(_id=_id)
if not queriedForm:
flash(gettext("Form is not available"), 'warning')
return redirect(make_url_for('my_forms'))
if request.method == 'POST':
if 'new_author_username' in request.form:
new_author=User(username=request.form['new_author_username'], hostname=g.site.hostname)
if new_author:
if new_author.enabled:
old_author=queriedForm.user # we really need to find better property names than author and user
if queriedForm.changeAuthor(new_author):
queriedForm.addLog(gettext("Changed author from %s to %s" % (old_author.username, new_author.username)))
flash(gettext("Changed author OK"), 'success')
return redirect(make_url_for('inspect_form', _id=queriedForm._id))
else:
flash(gettext("Cannot use %s. The user is not enabled" % request.form['new_author_username']), 'warning')
else:
flash(gettext("Can't find username %s" % request.form['new_author_username']), 'warning')
editors=[User(_id=user_id) for user_id in queriedForm.editors]
return render_template('change-author.html', form=queriedForm, editors=editors)
""" """
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment