Initial commit to support random auto admin password and first run wizard

This commit is contained in:
Roberto Rosario
2012-06-18 12:51:20 -04:00
parent 1bfa23c58a
commit 50b42238eb
12 changed files with 291 additions and 26 deletions

View File

@@ -4,9 +4,10 @@ import tempfile
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth import models as auth_models
from django.contrib.auth.models import User
from django.contrib.auth.management import create_superuser
from django.dispatch import receiver
from django.db.models.signals import post_syncdb
from django.db.models.signals import post_syncdb, post_save
from navigation.api import register_links, register_top_menu
@@ -14,6 +15,7 @@ from .conf.settings import (AUTO_CREATE_ADMIN, AUTO_ADMIN_USERNAME,
AUTO_ADMIN_PASSWORD, TEMPORARY_DIRECTORY)
from .conf import settings as common_settings
from .utils import validate_path
from .models import AutoAdminSingleton
def has_usable_password(context):
@@ -53,9 +55,22 @@ def create_superuser(sender, **kwargs):
print '*' * 80
print 'Creating super admin user -- login: %s, password: %s' % (AUTO_ADMIN_USERNAME, AUTO_ADMIN_PASSWORD)
print '*' * 80
assert auth_models.User.objects.create_superuser(AUTO_ADMIN_USERNAME, 'x@x.com', AUTO_ADMIN_PASSWORD)
assert auth_models.User.objects.create_superuser(AUTO_ADMIN_USERNAME, 'autoadmin@autoadmin.com', AUTO_ADMIN_PASSWORD)
admin = auth_models.User.objects.get(username=AUTO_ADMIN_USERNAME)
auto_admin_properties = AutoAdminSingleton.objects.get()
auto_admin_properties.auto_admin_account = admin
auto_admin_properties.auto_admin_password = AUTO_ADMIN_PASSWORD
auto_admin_properties.save()
else:
print 'Super admin user already exists. -- login: %s' % AUTO_ADMIN_USERNAME
@receiver(post_save, dispatch_uid='auto_admin_account_passwd_change', sender=User)
def auto_admin_account_passwd_change(sender, instance, **kwargs):
auto_admin_properties = AutoAdminSingleton.objects.get()
if instance == auto_admin_properties.auto_admin_account:
auto_admin_properties.delete(force=True)
if (validate_path(TEMPORARY_DIRECTORY) == False) or (not TEMPORARY_DIRECTORY):
setattr(common_settings, 'TEMPORARY_DIRECTORY', tempfile.mkdtemp())

View File

@@ -1,6 +1,7 @@
"""Configuration options for the common app"""
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User
from smart_settings.api import register_setting
@@ -53,7 +54,7 @@ register_setting(
module=u'common.conf.settings',
name=u'AUTO_ADMIN_PASSWORD',
global_name=u'COMMON_AUTO_ADMIN_PASSWORD',
default=u'admin',
default=User.objects.make_random_password(),
)
register_setting(

View File

@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'AnonymousUserSingleton'
db.create_table('common_anonymoususersingleton', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('lock_id', self.gf('django.db.models.fields.CharField')(default=1, unique=True, max_length=1)),
))
db.send_create_signal('common', ['AnonymousUserSingleton'])
def backwards(self, orm):
# Deleting model 'AnonymousUserSingleton'
db.delete_table('common_anonymoususersingleton')
models = {
'common.anonymoususersingleton': {
'Meta': {'object_name': 'AnonymousUserSingleton'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'lock_id': ('django.db.models.fields.CharField', [], {'default': '1', 'unique': 'True', 'max_length': '1'})
}
}
complete_apps = ['common']

View File

@@ -0,0 +1,77 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'AutoAdminSingleton'
db.create_table('common_autoadminsingleton', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('lock_id', self.gf('django.db.models.fields.CharField')(default=1, unique=True, max_length=1)),
('original_auto_admin_password', self.gf('django.db.models.fields.BooleanField')(default=True)),
('auto_admin', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True, blank=True)),
))
db.send_create_signal('common', ['AutoAdminSingleton'])
def backwards(self, orm):
# Deleting model 'AutoAdminSingleton'
db.delete_table('common_autoadminsingleton')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'common.anonymoususersingleton': {
'Meta': {'object_name': 'AnonymousUserSingleton'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'lock_id': ('django.db.models.fields.CharField', [], {'default': '1', 'unique': 'True', 'max_length': '1'})
},
'common.autoadminsingleton': {
'Meta': {'object_name': 'AutoAdminSingleton'},
'auto_admin': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'lock_id': ('django.db.models.fields.CharField', [], {'default': '1', 'unique': 'True', 'max_length': '1'}),
'original_auto_admin_password': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
}
}
complete_apps = ['common']

View File

@@ -0,0 +1,97 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Deleting field 'AutoAdminSingleton.original_auto_admin_password'
db.delete_column('common_autoadminsingleton', 'original_auto_admin_password')
# Deleting field 'AutoAdminSingleton.auto_admin'
db.delete_column('common_autoadminsingleton', 'auto_admin_id')
# Adding field 'AutoAdminSingleton.auto_admin_account'
db.add_column('common_autoadminsingleton', 'auto_admin_account',
self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='auto_admin_account', null=True, to=orm['auth.User']),
keep_default=False)
# Adding field 'AutoAdminSingleton.auto_admin_password'
db.add_column('common_autoadminsingleton', 'auto_admin_password',
self.gf('django.db.models.fields.CharField')(max_length=128, null=True, blank=True),
keep_default=False)
def backwards(self, orm):
# Adding field 'AutoAdminSingleton.original_auto_admin_password'
db.add_column('common_autoadminsingleton', 'original_auto_admin_password',
self.gf('django.db.models.fields.BooleanField')(default=True),
keep_default=False)
# Adding field 'AutoAdminSingleton.auto_admin'
db.add_column('common_autoadminsingleton', 'auto_admin',
self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True, blank=True),
keep_default=False)
# Deleting field 'AutoAdminSingleton.auto_admin_account'
db.delete_column('common_autoadminsingleton', 'auto_admin_account_id')
# Deleting field 'AutoAdminSingleton.auto_admin_password'
db.delete_column('common_autoadminsingleton', 'auto_admin_password')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'common.anonymoususersingleton': {
'Meta': {'object_name': 'AnonymousUserSingleton'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'lock_id': ('django.db.models.fields.CharField', [], {'default': '1', 'unique': 'True', 'max_length': '1'})
},
'common.autoadminsingleton': {
'Meta': {'object_name': 'AutoAdminSingleton'},
'auto_admin_account': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'auto_admin_account'", 'null': 'True', 'to': "orm['auth.User']"}),
'auto_admin_password': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'lock_id': ('django.db.models.fields.CharField', [], {'default': '1', 'unique': 'True', 'max_length': '1'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
}
}
complete_apps = ['common']

View File

View File

@@ -2,6 +2,7 @@ from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext
from django.contrib.auth.models import AnonymousUser
from django.contrib.auth.models import User
SINGLETON_LOCK_ID = 1
@@ -21,8 +22,9 @@ class Singleton(models.Model):
self.id = 1
super(Singleton, self).save(*args, **kwargs)
def delete(self):
pass
def delete(self, force=False, *args, **kwargs):
if force:
return super(Singleton, self).delete(*args, **kwargs)
class Meta:
abstract = True
@@ -45,3 +47,11 @@ class AnonymousUserSingleton(Singleton):
class Meta:
verbose_name = _(u'anonymous user')
verbose_name_plural = _(u'anonymous user')
class AutoAdminSingleton(Singleton):
auto_admin_account = models.ForeignKey(User, null=True, blank=True, related_name='auto_admin_account', verbose_name=_(u'auto admin'))
auto_admin_password = models.CharField(null=True, blank=True, verbose_name=_(u'auto admin password'), max_length=128)
class Meta:
verbose_name = verbose_name_plural = _(u'auto admin properties')

View File

@@ -0,0 +1,12 @@
from django.template import Library
from django.utils.importlib import import_module
from common.models import AutoAdminSingleton
register = Library()
@register.simple_tag(takes_context=True)
def auto_admin_properties(context):
context['auto_admin_properties'] = AutoAdminSingleton.objects.get()
return u''

View File

@@ -1,6 +1,7 @@
{% extends "web_theme_base.html" %}
{% load i18n %}
{% load theme_tags %}
{% load autoadmin_tags %}
{% block web_theme_head %}
{% if user.is_authenticated %}
@@ -28,27 +29,42 @@
{% endblock %}
{% else %}
{% block content_plain %}
{% auto_admin_properties %}
{% if auto_admin_properties.auto_admin_account %}
<div id="box">
<h1>{% block project_name %}{% endblock %}</h1>
<div class="block" id="block-login">
<h2>{% trans "Login" %}</h2>
<h2>{% trans "First time login" %}</h2>
<div class="content login">
<form action="." method="post" class="form login">{% csrf_token %}
<div class="group wat-cf">
{% include "generic_form_instance.html" %}
<input type="hidden" name="next" value="{{ next|escape }}" />
<div class="group navform wat-cf">
<button class="button" type="submit">
<img src="{{ STATIC_URL }}web_theme_media/images/icons/key.png" alt="Save" /> Login
</button>
</div>
</form>
<p>{% trans "You have just finished installing <strong>Mayan EDMS</strong>, congratulations!" %}</p>
<p>{% trans "Login using the following credentials:" %}</p>
<p>{% blocktrans with auto_admin_properties.auto_admin_account as auto_admin_account %}Username: <strong>{{ auto_admin_account }}</strong>{% endblocktrans %}</p>
<p>{% blocktrans with auto_admin_properties.auto_admin_password as auto_admin_password %}Password: <strong>{{ auto_admin_password }}</strong>{% endblocktrans %}</p>
<p>{% trans "Be sure to change the password to increase security and to disable this message." %}</p>
</div>
</div>
</div>
{% get_web_theme_setting "VERBOSE_LOGIN" as verbose_login %}
{% if verbose_login %}
{% include "verbose_login.html" %}
{% endif %}
{% endif %}
<div id="box">
<h1>{% block project_name %}{% endblock %}</h1>
<div class="block" id="block-login">
<h2>{% trans "Login" %}</h2>
<div class="content login">
<form action="." method="post" class="form login">{% csrf_token %}
<div class="group wat-cf">
{% include "generic_form_instance.html" %}
<input type="hidden" name="next" value="{{ next|escape }}" />
<div class="group navform wat-cf">
<button class="button" type="submit">
<img src="{{ STATIC_URL }}web_theme_media/images/icons/key.png" alt="Save" /> Login
</button>
</div>
</form>
</div>
</div>
</div>
{% get_web_theme_setting "VERBOSE_LOGIN" as verbose_login %}
{% if verbose_login %}
{% include "verbose_login.html" %}
{% endif %}
{% endblock %}
{% endif %}

View File

@@ -120,7 +120,7 @@ If using ``PostgreSQL``, enter the following::
Populate the database with the project's schema doing::
$ ./manage.py syncdb --migrate
$ ./manage.py syncdb --migrate --noinput
To test your installation, create a file called settings_local.py with the following content::
@@ -186,7 +186,7 @@ If using ``PostgreSQL``, enter the following::
Populate the database with the project's schema doing::
$ ./manage.py syncdb --migrate
$ ./manage.py syncdb --migrate --noinput
To test your installation, create a file called settings_local.py with the following content::
@@ -276,7 +276,7 @@ To install **Mayan EDMS** on Webfaction_, follow these steps:
6. Create the database schema::
$ ./manage.py syncdb --migrate
$ ./manage.py syncdb --migrate --noinput
7. Collect the static files of the apps::

View File

@@ -19,6 +19,9 @@ the diagnosis of installation of runtime error a simple view showing the
number of internal interval jobs being used by Mayan EDMS as well as a
new app which shows a detail of the current installation enviroment.
#TODO: Add auto admin random password
#TODO: auto admin first run login display
What's new in Mayan EDMS v0.12.2
================================
@@ -42,9 +45,11 @@ Upgrading from a previous version
Start off by adding the new requirements::
$ pip install -r requirements/production.txt
Migrate existing database schema with::
$ ./manage.py migrate common 0001 --fake
$ ./manage.py migrate common
$ ./manage.py migrate checkouts
The upgrade procedure is now complete.

View File

@@ -454,7 +454,7 @@ Username of the automatically created superuser
**COMMON_AUTO_ADMIN_PASSWORD**
Default: ``admin``
Default: Random generated password
Default password of the automatically created superuser