From d095478e4fda744acbc1f5374229823937c92b49 Mon Sep 17 00:00:00 2001 From: Raynaldo Rivera Date: Wed, 8 Oct 2014 00:46:58 -0700 Subject: [PATCH] Added full services working, refresh, create, delete, updated look --- allianceauth/settings.py | 12 +- allianceauth/urls.py | 18 ++- authentication/models.py | 16 +- portal/views.py | 183 ++++++++++++++++++---- services/jabber_manager.py | 58 +++++-- services/mumble_manager.py | 89 ++++++++--- services/phpbb3_manager.py | 110 +++++++++---- static/css/updatecards.css | 28 ++-- templates/public/base.html | 20 +-- templates/registered/apikeymanagment.html | 2 +- templates/registered/characters.html | 44 +++--- templates/registered/dashboard.html | 4 +- templates/registered/help.html | 15 ++ templates/registered/services.html | 39 +++-- util/context_processors.py | 8 +- 15 files changed, 463 insertions(+), 183 deletions(-) create mode 100644 templates/registered/help.html diff --git a/allianceauth/settings.py b/allianceauth/settings.py index 4aeb3b0e..8c63d05c 100644 --- a/allianceauth/settings.py +++ b/allianceauth/settings.py @@ -128,7 +128,8 @@ TEMPLATE_CONTEXT_PROCESSORS = ( 'django.contrib.messages.context_processors.messages', 'django.core.context_processors.request', 'util.context_processors.alliance_id', - 'util.context_processors.alliance_name' + 'util.context_processors.alliance_name', + 'util.context_processors.jabber_url' ) ########## USER CONFIGURATION @@ -151,12 +152,13 @@ STATICFILES_DIRS = ( STATIC_URL = '/static/' # ALLIANCE INFO -ALLIANCE_ID = '99001336' -ALLIANCE_NAME = 'The 99 Percent' +ALLIANCE_ID = '0' +ALLIANCE_NAME = 'some alliance' # Jabber Prosody Info -OPENFIRE_ADDRESS = "http://the99eve.com:9090/" -OPENFIRE_SECRET_KEY = "SrJ35I36" +JABBER_URL = "@someurl.com" +OPENFIRE_ADDRESS = "http://someurl.com:9090/" +OPENFIRE_SECRET_KEY = "somekey" # Mumble settings MUMBLE_SERVER_ID = 1 \ No newline at end of file diff --git a/allianceauth/urls.py b/allianceauth/urls.py index 17019372..2aac74c6 100644 --- a/allianceauth/urls.py +++ b/allianceauth/urls.py @@ -7,10 +7,13 @@ urlpatterns = patterns('', # Main Views url(r'^$', 'portal.views.index_view', name='auth_index'), + + # Registered Views url(r'^dashboard/$', 'portal.views.dashboard_view', name='auth_dashboard'), url(r'^characters/', 'portal.views.characters_view', name='auth_characters'), url(r'^api_key_management/', 'portal.views.api_key_management_view', name='auth_api_key_management'), url(r'^services/', 'portal.views.services_view', name='auth_services'), + url(r'^help/', 'portal.views.help_view', name='auth_help'), # Register url(r'^register/', 'registration.views.register', name='auth_register'), @@ -21,8 +24,21 @@ urlpatterns = patterns('', # None views url(r'^main_character_change/(\w+)/$', 'portal.views.main_character_change', name='auth_main_character_change'), + url(r'^delete_api_pair/(\w+)/$', 'portal.views.api_key_removal', name='auth_api_key_removal'), + + # Forum Service Control url(r'^activate_forum/$', 'portal.views.activate_forum', name='auth_activate_forum'), + url(r'^deactivate_forum/$', 'portal.views.deactivate_forum', name='auth_deactivate_forum'), + url(r'reset_forum_password/$', 'portal.views.reset_forum_password', name='auth_reset_forum_password'), + + # Jabber Service Control url(r'^activate_jabber/$', 'portal.views.activate_jabber', name='auth_activate_jabber'), + url(r'^deactivate_jabber/$', 'portal.views.deactivate_jabber', name='auth_deactivate_jabber'), + url(r'^reset_jabber_password/$', 'portal.views.reset_jabber_password', name='auth_reset_jabber_password'), + + # Mumble service contraol url(r'^activate_mumble/$', 'portal.views.activate_mumble', name='auth_activate_mumble'), - url(r'^delete_api_pair/(\w+)/$', 'portal.views.api_key_removal', name='auth_api_key_removal') + url(r'deactivate_mumble/$', 'portal.views.deactivate_mumble', name='auth_deactivate_mumble'), + url(r'reset_mumble_password/$', 'portal.views.reset_mumble_password', name='auth_reset_mumble_password'), + ) diff --git a/authentication/models.py b/authentication/models.py index 8ef1af9a..1c37939b 100644 --- a/authentication/models.py +++ b/authentication/models.py @@ -49,7 +49,7 @@ class AllianceUserManager(BaseUserManager): def check_if_user_exist_by_name(self, user_name): return AllianceUser.objects.filter(username=user_name).exists() - def update_user_form_info(self, username, password, user_id): + def update_user_forum_info(self, username, password, user_id): if AllianceUser.objects.filter(id=user_id).exists(): user = AllianceUser.objects.get(id=user_id) user.forum_username = username @@ -86,7 +86,7 @@ class AllianceUserManager(BaseUserManager): content_type=ct, name='Alliance Member') if AllianceUser.objects.filter(id=user_id).exists(): user = AllianceUser.objects.get(id=user_id) - if user.has_perm('authentication.alliance_member'): + if user.has_perm('alliance_member'): user.user_permissions.remove(permission) user.save() @@ -100,12 +100,12 @@ class AllianceUser(AbstractBaseUser, PermissionsMixin): main_char_id = models.CharField(max_length=64, default="") # Login information stuff - forum_username = models.CharField(max_length=64) - forum_password = models.CharField(max_length=64) - jabber_username = models.CharField(max_length=64) - jabber_password = models.CharField(max_length=64) - mumble_username = models.CharField(max_length=64) - mumble_password = models.CharField(max_length=64) + forum_username = models.CharField(max_length=254) + forum_password = models.CharField(max_length=254) + jabber_username = models.CharField(max_length=254) + jabber_password = models.CharField(max_length=254) + mumble_username = models.CharField(max_length=254) + mumble_password = models.CharField(max_length=254) objects = AllianceUserManager() diff --git a/portal/views.py b/portal/views.py index 80559b55..c145268b 100644 --- a/portal/views.py +++ b/portal/views.py @@ -3,7 +3,6 @@ from django.conf import settings from django.template import RequestContext from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import permission_required -from django.contrib.auth.models import Permission from services.eveapi_manager import EveApiManager from evespecific.managers import EveManager @@ -80,6 +79,11 @@ def services_view(request): return render_to_response('registered/services.html', None, context_instance=RequestContext(request)) +@login_required +def help_view(request): + return render_to_response('registered/help.html', None, context_instance=RequestContext(request)) + + @login_required def main_character_change(request, char_id): usermanager = AllianceUserManager() @@ -98,52 +102,163 @@ def main_character_change(request, char_id): @login_required -@permission_required('auth.alliance_member') +@permission_required('authentication.alliance_member') def activate_forum(request): - userManager = AllianceUserManager() - forumManager = Phpbb3Manager() + usermanager = AllianceUserManager() + forummanager = Phpbb3Manager() - if userManager.check_if_user_exist(request.user.id): + if usermanager.check_if_user_exist_by_id(request.user.id): # Valid now we get the main characters - characterManager = EveManager() - character = characterManager.get_character_by_id(request.user.main_char_id) - - if forumManager.check_user(character.character_name) == False: - forumManager.add_user(character.character_name, "test", request.user.email, ['REGISTERED']) + charactermanager = EveManager() + character = charactermanager.get_character_by_id(request.user.main_char_id) + + result = forummanager.add_user(character.character_name, request.user.email, ['REGISTERED']) + + # if empty we failed + if result[0] != "": + usermanager.update_user_forum_info(result[0], result[1], request.user.id) + + return HttpResponseRedirect("/services/") + + return HttpResponseRedirect("/dashboard") + +@login_required +@permission_required('authentication.alliance_member') +def deactivate_forum(request): + usermanager = AllianceUserManager() + forummanager = Phpbb3Manager() + + if usermanager.check_if_user_exist_by_id(request.user.id): + + result = forummanager.disable_user(request.user.forum_username) + + # false we failed + if result: + usermanager.update_user_forum_info("", "", request.user.id) + return HttpResponseRedirect("/services/") + + return HttpResponseRedirect("/dashboard") + +@login_required +@permission_required('authentication.alliance_member') +def reset_forum_password(request): + usermanager = AllianceUserManager() + forummanager = Phpbb3Manager() + + if usermanager.check_if_user_exist_by_id(request.user.id): + + result = forummanager.update_user_password(request.user.forum_username) + + # false we failed + if result != "": + usermanager.update_user_forum_info(request.user.forum_username, result, request.user.id) + return HttpResponseRedirect("/services/") + + return HttpResponseRedirect("/dashboard") + +@login_required +@permission_required('authentication.alliance_member') +def activate_jabber(request): + usermanager = AllianceUserManager() + jabbermanager = JabberManager() + if usermanager.check_if_user_exist_by_id(request.user.id): + charactermanager = EveManager() + character = charactermanager.get_character_by_id(request.user.main_char_id) + + info = jabbermanager.add_user(character.character_name) + + # If our username is blank means we already had a user + if info[0] is not "": + usermanager.update_user_jabber_info(info[0], info[1], request.user.id) + return HttpResponseRedirect("/services/") + + return HttpResponseRedirect("/dashboard") + + +@login_required +@permission_required('authentication.alliance_member') +def deactivate_jabber(request): + usermanager = AllianceUserManager() + jabbermanager = JabberManager() + if usermanager.check_if_user_exist_by_id(request.user.id): + result = jabbermanager.delete_user(request.user.jabber_username) + # If our username is blank means we failed + if result: + usermanager.update_user_jabber_info("", "", request.user.id) + + return HttpResponseRedirect("/services/") + + return HttpResponseRedirect("/dashboard") + +@login_required +@permission_required('authentication.alliance_member') +def reset_jabber_password(request): + usermanager = AllianceUserManager() + jabbermanager = JabberManager() + if usermanager.check_if_user_exist_by_id(request.user.id): + result = jabbermanager.update_user_pass(request.user.jabber_username) + # If our username is blank means we failed + if result != "": + usermanager.update_user_jabber_info(request.user.jabber_username, result, request.user.id) + + return HttpResponseRedirect("/services/") + + return HttpResponseRedirect("/dashboard") + + +@login_required +@permission_required('authentication.alliance_member') +def activate_mumble(request): + usermanager = AllianceUserManager() + charactermanager = EveManager() + mumblemanager = MumbleManager() + + if usermanager.check_if_user_exist_by_id(request.user.id): + character = charactermanager.get_character_by_id(request.user.main_char_id) + + result = mumblemanager.create_user(character.corporation_ticker, character.character_name) + + # if its empty we failed + if result[0] is not "": + usermanager.update_user_mumble_info(result[0], result[1], request.user.id) + return HttpResponseRedirect("/services/") return HttpResponseRedirect("/") - @login_required -@permission_required('auth.alliance_member') -def activate_jabber(request): - userManager = AllianceUserManager() - jabberManager = JabberManager() - if userManager.check_if_user_exist(request.user.id): - characterManager = EveManager() - character = characterManager.get_character_by_id(request.user.main_char_id) - - jabberManager.add_user(character.character_name,"test") - - return HttpResponseRedirect("/services/") - +@permission_required('authentication.alliance_member') +def deactivate_mumble(request): + usermanager = AllianceUserManager() + mumblemanager = MumbleManager() + + if usermanager.check_if_user_exist_by_id(request.user.id): + + result = mumblemanager.delete_user(request.user.mumble_username) + + # if false we failed + if result: + usermanager.update_user_mumble_info("", "", request.user.id) + + return HttpResponseRedirect("/services/") + return HttpResponseRedirect("/") - @login_required -@permission_required('auth.alliance_member') -def activate_mumble(request): - userManager = AllianceUserManager() - characterManager = EveManager() - mumbleManager = MumbleManager() +@permission_required('authentication.alliance_member') +def reset_mumble_password(request): - if userManager.check_if_user_exist(request.user.id): - characterManager = EveManager() - character = characterManager.get_character_by_id(request.user.main_char_id) + usermanager = AllianceUserManager() + mumblemanager = MumbleManager() - mumbleManager.create_user(character.character_name, "test") + if usermanager.check_if_user_exist_by_id(request.user.id): - return HttpResponseRedirect("/services/") + result = mumblemanager.update_user_password(request.user.mumble_username) + + # if blank we failed + if result != "": + usermanager.update_user_mumble_info(request.user.mumble_username, result, request.user.id) + + return HttpResponseRedirect("/services/") return HttpResponseRedirect("/") \ No newline at end of file diff --git a/services/jabber_manager.py b/services/jabber_manager.py index 2c33f4b4..df2566fb 100644 --- a/services/jabber_manager.py +++ b/services/jabber_manager.py @@ -1,21 +1,48 @@ +import os from django.conf import settings +from openfire import exception from openfire import UserService +from urlparse import urlparse class JabberManager(): def __init__(self): pass - - def add_user(self, username, password): - api = UserService(settings.OPENFIRE_ADDRESS, settings.OPENFIRE_SECRET_KEY) - print str(username) - print str(password) - api.add_user(self.__santatize_username(username), str(password)) + + def __add_address_to_username(self, username): + address = urlparse(settings.OPENFIRE_ADDRESS).netloc.split(":")[0] + completed_username = username + "@" + address + return completed_username + + def __santatize_username(self, username): + sanatized = username.replace(" ", "_") + return sanatized.lower() + + def __generate_random_pass(self): + return os.urandom(8).encode('hex') + + def add_user(self, username): + + try: + sanatized_username = self.__santatize_username(username) + password = self.__generate_random_pass() + api = UserService(settings.OPENFIRE_ADDRESS, settings.OPENFIRE_SECRET_KEY) + api.add_user(sanatized_username, password) + + except exception.UserAlreadyExistsException: + # User exist + return "", "" + + return sanatized_username, password def delete_user(self, username): - api = UserService(settings.OPENFIRE_ADDRESS, settings.OPENFIRE_SECRET_KEY) - api.delete_user(username) + try: + api = UserService(settings.OPENFIRE_ADDRESS, settings.OPENFIRE_SECRET_KEY) + api.delete_user(username) + return True + except exception.UserNotFoundException: + return False def lock_user(self, username): api = UserService(settings.OPENFIRE_ADDRESS, settings.OPENFIRE_SECRET_KEY) @@ -25,10 +52,11 @@ class JabberManager(): api = UserService(settings.OPENFIRE_ADDRESS, settings.OPENFIRE_SECRET_KEY) api.unlock_user(username) - def update_user_pass(self, username, password): - api = UserService(settings.OPENFIRE_ADDRESS, settings.OPENFIRE_SECRET_KEY) - api.update_user(username, password) - - def __santatize_username(self, username): - sanatized = username.replace(" ", "_") - return sanatized.lower() \ No newline at end of file + def update_user_pass(self, username): + try: + password = self.__generate_random_pass() + api = UserService(settings.OPENFIRE_ADDRESS, settings.OPENFIRE_SECRET_KEY) + api.update_user(username, password) + return password + except exception.UserNotFoundException: + return "" diff --git a/services/mumble_manager.py b/services/mumble_manager.py index 316495fd..910f52cb 100644 --- a/services/mumble_manager.py +++ b/services/mumble_manager.py @@ -1,38 +1,61 @@ -import uuid +import os import hashlib -import random from django.db import connections from django.conf import settings + class MumbleManager: + SQL_SELECT_MAX_ID = r"SELECT max(user_id)+1 as next_id from murmur_users" + SQL_CREATE_USER = r"INSERT INTO murmur_users (server_id, user_id, name, pw) VALUES (%s, %s, %s, %s)" + SQL_SELECT_GET_USER_ID_BY_NAME = r"SELECT user_id from murmur_users WHERE name = %s AND server_id = %s" + SQL_CHECK_USER_EXIST = r"SELECT name from murmur_users WHERE name = %s AND server_id = %s" + SQL_DELETE_USER = r"DELETE FROM murmur_users WHERE name = %s AND server_id = %s" + SQL_UPDATE_USER_PASSWORD = r"UPDATE murmur_users SET pw = %s WHERE name = %s AND server_id = %s" + def __init__(self): self.dbcursor = connections['mumble'].cursor() - @staticmethod - def _gen_pwhash(password): + def __santatize_username(self, username): + sanatized = username.replace(" ", "_") + return sanatized + + def __generate_random_pass(self): + return os.urandom(8).encode('hex') + + def __generate_username(self, username, corp_ticker): + return "["+corp_ticker+"]"+username + + def _gen_pwhash(self, password): return hashlib.sha1(password).hexdigest() def get_user_id_by_name(self, name): - self.dbcursor.execute(r"SELECT user_id from murmur_users WHERE name = %s AND server_id = %s", - [name, settings.MUMBLE_SERVER_ID]) + self.dbcursor.execute(self.SQL_SELECT_GET_USER_ID_BY_NAME, [name, settings.MUMBLE_SERVER_ID]) row = self.dbcursor.fetchone() if row: return row[0] - def create_user(self, username, password): - """ Add a user """ - self.dbcursor.execute(r"SELECT max(user_id)+1 as next_id from murmur_users") - user_id = self.dbcursor.fetchone()[0] + def create_user(self, corp_ticker, username): - self.dbcursor.execute(r"INSERT INTO murmur_users (server_id, user_id, name, pw) VALUES (%s, %s, %s, %s)", - [settings.MUMBLE_SERVER_ID, user_id, self.__santatize_username(username), self._gen_pwhash(password)]) + username_clean = self.__generate_username(self.__santatize_username(username), corp_ticker) + password = self.__generate_random_pass() + pwhash = self._gen_pwhash(password) - return {'username': username, 'password': password } + try: + self.dbcursor.execute(self.SQL_SELECT_MAX_ID) + user_id = self.dbcursor.fetchone()[0] + + self.dbcursor.execute(self.SQL_CREATE_USER, + [settings.MUMBLE_SERVER_ID, user_id, username_clean, + pwhash]) + + return username_clean, password + except: + return "", "" def check_user_exist(self, username): - """ Check if the username exists """ - self.dbcursor.execute(r"SELECT name from murmur_users WHERE name = %s AND server_id = %s", + + self.dbcursor.execute(self.SQL_CHECK_USER_EXIST, [username, settings.MUMBLE_SERVER_ID]) row = self.dbcursor.fetchone() @@ -40,13 +63,31 @@ class MumbleManager: return True return False - def delete_user(self, uid): - """ Delete a user """ - id = self.get_user_id_by_name(uid) - self.dbcursor.execute(r"DELETE FROM murmur_users WHERE user_id = %s AND server_id = %s", - [id, settings.MUMBLE_SERVER_ID]) - return True + def delete_user(self, username): - def __santatize_username(self, username): - sanatized = username.replace(" ","_") - return sanatized.lower() \ No newline at end of file + if self.check_user_exist(username): + try: + + self.dbcursor.execute(self.SQL_DELETE_USER, + [username, settings.MUMBLE_SERVER_ID]) + return True + except: + return False + + return False + + def update_user_password(self, username): + + password = self.__generate_random_pass() + pwhash = self._gen_pwhash(password) + + if self.check_user_exist(username): + try: + + self.dbcursor.execute(self.SQL_UPDATE_USER_PASSWORD, + [pwhash, username, settings.MUMBLE_SERVER_ID]) + return password + except: + return "" + + return "" \ No newline at end of file diff --git a/services/phpbb3_manager.py b/services/phpbb3_manager.py index b1ea0262..3758d70b 100644 --- a/services/phpbb3_manager.py +++ b/services/phpbb3_manager.py @@ -1,4 +1,5 @@ -import random +import os +import sys from passlib.apps import phpbb3_context from django.db import connections @@ -9,8 +10,9 @@ class Phpbb3Manager(): r"user_password, user_email, group_id , user_permissions, " \ r"user_sig, user_occ, user_interests) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)" - SQL_DIS_USER = r"DELETE FROM phpbb_user_groups where user_id = " \ - r"(SELECT user_id FROM phpbb_users WHERE username = %s)" + SQL_DEL_USER = r"DELETE FROM phpbb_users where username = %s" + + SQL_DIS_USER = r"UPDATE phpbb_users SET user_email= %s, user_password=%s WHERE username = %s" SQL_CHECK_USER = r"SELECT user_id from phpbb_users WHERE username = %s" @@ -19,49 +21,91 @@ class Phpbb3Manager(): SQL_GET_GROUP = r"SELECT group_id from phpbb_groups WHERE group_name = %s" SQL_ADD_GROUP = r"INSERT INTO phpbb_groups (group_name) VALUES (%s)" - - def __init__(self): - pass - - def _gen_salt(self): - return "%x" % random.randint(0, 2147483647) - def _gen_hash(self, password): + SQL_UPDATE_USER_PASSWORD = r"UPDATE phpbb_users SET user_password = %s WHERE username = %s" + + def __init__(self): + self.cursor = connections['phpbb3'].cursor() + + def __generate_random_pass(self): + return os.urandom(8).encode('hex') + + def __gen_hash(self, password): return phpbb3_context.encrypt(password) - - def add_user(self, username, password, email, groups): - - cursor = connections['phpbb3'].cursor() - - """ Add a user """ - username_clean = username.lower() - pwhash = self._gen_hash(password) - cursor.execute(self.SQL_ADD_USER, [username, username_clean, pwhash, email, 2, "", "","", ""]) - self.update_groups(username,groups) - return { 'username': username, 'password': password } + + def __santatize_username(self, username): + sanatized = username.replace(" ", "_") + return sanatized.lower() + + def add_user(self, username, email, groups): + username_clean = self.__santatize_username(username) + password = self.__generate_random_pass() + pwhash = self.__gen_hash(password) + + # check if the username was simply revoked + if self.check_user(username_clean): + self.__update_user_info(username_clean, email, pwhash) + else: + try: + self.cursor.execute(self.SQL_ADD_USER, [username_clean, username_clean, pwhash, email, 2, "", "", "", ""]) + self.update_groups(username_clean, groups) + except: + pass + + return username_clean, password + + def disable_user(self, username): + password = self.__gen_hash(self.__generate_random_pass()) + revoke_email = "revoked@the99eve.com" + try: + pwhash = self.__gen_hash(password) + self.cursor.execute(self.SQL_DIS_USER, [revoke_email, pwhash, username]) + return True + except TypeError as e: + print e + return False + + def delete_user(self, username): + if self.check_user(username): + self.cursor.execute(self.SQL_DEL_USER, [username]) + return True + return False def update_groups(self, username, groups): - cursor = connections['phpbb3'].cursor() - - cursor.execute(self.SQL_CHECK_USER, [username]) - row = cursor.fetchone() + self.cursor.execute(self.SQL_CHECK_USER, [username]) + row = self.cursor.fetchone() userid = row[0] for group in groups: - cursor.execute(self.SQL_GET_GROUP, [group]) - row = cursor.fetchone() + self.cursor.execute(self.SQL_GET_GROUP, [group]) + row = self.cursor.fetchone() print row if not row: - cursor.execute(self.SQL_ADD_GROUP, [group]) - cursor.execute(self.SQL_GET_GROUP, [group]) - row = cursor.fetchone() + self.cursor.execute(self.SQL_ADD_GROUP, [group]) + self.cursor.execute(self.SQL_GET_GROUP, [group]) + row = self.cursor.fetchone() - cursor.execute(self.SQL_ADD_USER_GROUP, [row[0], userid,0]) + self.cursor.execute(self.SQL_ADD_USER_GROUP, [row[0], userid,0]) def check_user(self, username): cursor = connections['phpbb3'].cursor() """ Check if the username exists """ - cursor.execute(self.SQL_CHECK_USER, [username]) + cursor.execute(self.SQL_CHECK_USER, [self.__santatize_username(username)]) row = cursor.fetchone() if row: return True - return False \ No newline at end of file + return False + + def update_user_password(self, username): + password = self.__generate_random_pass() + if self.check_user(username): + pwhash = self.__gen_hash(password) + self.cursor.execute(self.SQL_UPDATE_USER_PASSWORD, [pwhash, username]) + return password + + return "" + + def __update_user_info(self, username, email, password): + try: + self.cursor.execute(self.SQL_DIS_USER, [email, password, username]) + except: + pass \ No newline at end of file diff --git a/static/css/updatecards.css b/static/css/updatecards.css index afe65aa7..bfb10394 100644 --- a/static/css/updatecards.css +++ b/static/css/updatecards.css @@ -2,7 +2,7 @@ body { font-family: 'Lato', 'sans-serif'; } -.profile +.profile { min-height: 150px; width: 450px; @@ -22,15 +22,15 @@ figcaption.ratings a:hover color:#f39c12; text-decoration:none; } -.divider +.divider { border-top:1px solid rgba(0,0,0,0.1); } -.emphasis +.emphasis { border-top: 4px solid transparent; } -.emphasis:hover +.emphasis:hover { border-top: 4px solid #1abc9c; } @@ -38,7 +38,7 @@ figcaption.ratings a:hover { margin-bottom:0; } -span.tags +span.tags { background: #1abc9c; border-radius: 2px; @@ -46,28 +46,28 @@ span.tags font-weight: bold; padding: 2px 4px; } -.dropdown-menu +.dropdown-menu { - background-color: #34495e; + background-color: #34495e; box-shadow: none; -webkit-box-shadow: none; width: 250px; margin-left: -125px; left: 50%; } -.dropdown-menu .divider +.dropdown-menu .divider { - background:none; + background:none; } .dropdown-menu>li>a { color:#f5f5f5; } -.dropup .dropdown-menu +.dropup .dropdown-menu { margin-bottom:10px; } -.dropup .dropdown-menu:before +.dropup .dropdown-menu:before { content: ""; border-top: 10px solid #34495e; @@ -78,4 +78,8 @@ span.tags left: 50%; margin-left: -10px; z-index: 10; - } \ No newline at end of file + } + +.fixed_button_width { + width: 78px !important; +} diff --git a/templates/public/base.html b/templates/public/base.html index 96eba007..34bf2ea8 100644 --- a/templates/public/base.html +++ b/templates/public/base.html @@ -28,14 +28,10 @@