diff --git a/avatar/templates/avatar/set_avatar.html b/avatar/templates/avatar/set_avatar.html index e3c9864bee..bec85474ed 100644 --- a/avatar/templates/avatar/set_avatar.html +++ b/avatar/templates/avatar/set_avatar.html @@ -1,4 +1,4 @@ -{% extends "myhome_base.html" %} +{% extends base_template %} {% load group_avatar_tags %} {% block nav_group_class %}class="cur"{% endblock %} diff --git a/base/context_processors.py b/base/context_processors.py index 4944bf1b6e..4c9d4b6b89 100644 --- a/base/context_processors.py +++ b/base/context_processors.py @@ -18,3 +18,4 @@ def base(request): 'seahub_title': settings.SEAHUB_TITLE, 'account_type': settings.ACCOUNT_TYPE, } + diff --git a/group/templates/group/group_info.html b/group/templates/group/group_info.html index 8e38cf0c34..25685ff936 100644 --- a/group/templates/group/group_info.html +++ b/group/templates/group/group_info.html @@ -1,4 +1,4 @@ -{% extends "myhome_base.html" %} +{% extends base_template %} {% load seahub_tags avatar_tags %} {% block nav_group_class %}class="cur"{% endblock %} diff --git a/group/templates/group/group_manage.html b/group/templates/group/group_manage.html index e22eb891d4..5bbba29981 100644 --- a/group/templates/group/group_manage.html +++ b/group/templates/group/group_manage.html @@ -1,4 +1,4 @@ -{% extends "myhome_base.html" %} +{% extends base_template %} {% load seahub_tags %} {% block nav_group_class %}class="cur"{% endblock %} diff --git a/group/templates/group/new_msg_reply.html b/group/templates/group/new_msg_reply.html index bca2bbac15..054539841c 100644 --- a/group/templates/group/new_msg_reply.html +++ b/group/templates/group/new_msg_reply.html @@ -1,4 +1,4 @@ -{% extends "myhome_base.html" %} +{% extends base_template %} {% load seahub_tags avatar_tags %} {% block nav_group_class %}class="cur"{% endblock %} diff --git a/group/views.py b/group/views.py index 9282f7d6f3..dea3e1421f 100644 --- a/group/views.py +++ b/group/views.py @@ -64,8 +64,11 @@ def group_remove(request, group_id): seafserv_threaded_rpc.remove_repo_group(group_id_int, None) if request.user.org: - ccnet_threaded_rpc.remove_org_group(request.user.org.org_id, - group_id_int) + org_id = request.user.org['org_id'] + url_prefix = request.user.org['url_prefix'] + ccnet_threaded_rpc.remove_org_group(org_id, group_id_int) + return HttpResponseRedirect(reverse('org_groups', + args=[url_prefix])) except SearpcError, e: return go_error(request, e.msg) diff --git a/organizations/__init__.py b/organizations/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/organizations/context_processors.py b/organizations/context_processors.py new file mode 100644 index 0000000000..a74f5b7c7a --- /dev/null +++ b/organizations/context_processors.py @@ -0,0 +1,16 @@ +def org(request): + """ + Add org info and base template that html page will extends to context. + """ + if hasattr(request.user, 'org') and request.user.org is not None: + if request.user.org['is_staff']: + base_template = 'org_admin_base.html' + else: + base_template = 'org_base.html' + return {'cur_ctx': 'org', + 'org': request.user.org, + 'base_template': base_template} + else: + return {'cur_ctx': '', + 'base_template': 'myhome_base.html'} + diff --git a/organizations/forms.py b/organizations/forms.py new file mode 100644 index 0000000000..f83c93463f --- /dev/null +++ b/organizations/forms.py @@ -0,0 +1,19 @@ +# encoding: utf-8 +from django import forms +from seaserv import ccnet_threaded_rpc + +class OrgCreateForm(forms.Form): + org_name = forms.CharField(max_length=256, + widget=forms.TextInput(), + label="Organization Name") + url_prefix = forms.RegexField(label="Url Prefix", max_length=20, + regex=r'^[a-z0-9]+$', + error_message="域名前缀只能包含字母或数字") + + def clean_url_prefix(self): + url_prefix = self.cleaned_data['url_prefix'] + org = ccnet_threaded_rpc.get_org_by_url_prefix(url_prefix) + if not org: + return url_prefix + else: + raise forms.ValidationError("该域名前缀已被注册") diff --git a/organizations/middleware.py b/organizations/middleware.py new file mode 100644 index 0000000000..642a753023 --- /dev/null +++ b/organizations/middleware.py @@ -0,0 +1,30 @@ +from django.core.cache import cache +from django.http import HttpResponseRedirect + +from seaserv import get_org_by_url_prefix + +from settings import ORG_CACHE_PREFIX + +class OrganizationMiddleware(object): + """ + Middleware that add organization info to request when user in organization + context. + """ + + def process_request(self, request): + """ + """ + org = cache.get(ORG_CACHE_PREFIX + request.user.username) + request.user.org = org + + # full_path = request.get_full_path() + # if full_path.startswith('/organizations/'): + # url_prefix = full_path.split('/')[2] + # org = get_org_by_url_prefix(url_prefix) + # if org: + # request.org = org + + return None + + def process_response(self, request, response): + return response diff --git a/organizations/models.py b/organizations/models.py new file mode 100644 index 0000000000..71a8362390 --- /dev/null +++ b/organizations/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/organizations/settings.py b/organizations/settings.py new file mode 100644 index 0000000000..f18fa87b54 --- /dev/null +++ b/organizations/settings.py @@ -0,0 +1,3 @@ +from django.conf import settings + +ORG_CACHE_PREFIX = getattr(settings, 'ORG_CACHE_PREFIX', 'ORGANIZATION_') diff --git a/organizations/templates/organizations/change_account.html b/organizations/templates/organizations/change_account.html new file mode 100644 index 0000000000..597838ea1a --- /dev/null +++ b/organizations/templates/organizations/change_account.html @@ -0,0 +1,48 @@ +{% extends base_template %} +{% load avatar_tags %} + +{% block left_panel %} + +

操作

+ + +{% endblock %} + +{% block right_panel %} +
+

切换帐号

+ + + + + + + + + +{% for org in orgs %} + + + + +{% endfor %} +
名称操作
{{ request.user}}
{{ org.org_name }}
+
+ +
+
+
+ +{% endblock %} + +{% block extra_script %} + +{% endblock %} + diff --git a/organizations/templates/organizations/create_org.html b/organizations/templates/organizations/create_org.html new file mode 100644 index 0000000000..1d3456dae2 --- /dev/null +++ b/organizations/templates/organizations/create_org.html @@ -0,0 +1,20 @@ +{% extends base_template %} +{% block main_panel %} +
+

创建企业帐号

+
+ + {{ form.org_name}} + 域名前缀: + {{ form.url_prefix }} +

+ {{ form.url_prefix.errors }} + + +
+{% endblock %} + +{% block extra_script %} + +{% endblock %} diff --git a/organizations/templates/organizations/org_groups.html b/organizations/templates/organizations/org_groups.html new file mode 100644 index 0000000000..6790e371b0 --- /dev/null +++ b/organizations/templates/organizations/org_groups.html @@ -0,0 +1,52 @@ +{% extends "org_base.html" %} +{% load seahub_tags group_avatar_tags %} + +{% block nav_group_class %}class="cur"{% endblock %} +{% block left_panel %} +

操作

+ +{% endblock %} + +{% block right_panel %} + +

{{ org.org_name }} 的小组

+{% if groups %} + +{% else %} +

暂无

+{% endif %} + +
+
+
+ +
+ +{% endblock %} + +{% block extra_script %} + +{% endblock %} diff --git a/organizations/templates/organizations/org_info.html b/organizations/templates/organizations/org_info.html new file mode 100644 index 0000000000..edb5b02b58 --- /dev/null +++ b/organizations/templates/organizations/org_info.html @@ -0,0 +1,82 @@ +{% extends "org_base.html" %} +{% load seahub_tags avatar_tags %} + +{% block nav_org_class %}class="cur"{% endblock %} + +{% block main_panel %} +
+

企业成员

+{% if org_users %} + +{% else %} +

暂无

+{% endif %} + +{% if is_join %} +

操作

+ +{% endif %} +
+ +
+

{{ org.org_name }} 公开的同步目录

+ + + + + + + + +{% if repos %} + {% for repo in repos %} + + + + {% if repo.latest_modify %} + + {% else %} + + {% endif %} + + + {% endfor %} +{% endif %} +
名字描述更新时间操作
{{ repo.props.name }}{{ repo.props.desc }}{{ repo.latest_modify|translate_commit_time }}—— —— + 同步 + + 删除 +
+ +
+{% endblock %} + +{% block extra_script %} + +{% endblock %} diff --git a/organizations/tests.py b/organizations/tests.py new file mode 100644 index 0000000000..501deb776c --- /dev/null +++ b/organizations/tests.py @@ -0,0 +1,16 @@ +""" +This file demonstrates writing tests using the unittest module. These will pass +when you run "manage.py test". + +Replace this with more appropriate tests for your application. +""" + +from django.test import TestCase + + +class SimpleTest(TestCase): + def test_basic_addition(self): + """ + Tests that 1 + 1 always equals 2. + """ + self.assertEqual(1 + 1, 2) diff --git a/organizations/urls.py b/organizations/urls.py new file mode 100644 index 0000000000..14aa7bd47d --- /dev/null +++ b/organizations/urls.py @@ -0,0 +1,20 @@ +from django.conf.urls.defaults import * + +from views import * +from seahub.views import repo, repo_history, org_seafadmin, org_useradmin, \ + org_group_admin + +urlpatterns = patterns('', + (r'^create/$', create_org), + (r'^change_account/$', change_account), + (r'^(?P[^/]+)/$', org_info), + url(r'^(?P[^/]+)/groups/$', org_groups, name='org_groups'), + + url(r'^([^/]+)/repo/(?P[^/]+)/$', repo, name='repo'), + url(r'^([^/]+)/repo/history/(?P[^/]+)/$', repo_history, name='org_repo_history'), + + ### Org admin ### + url(r'^([^/]+)/seafadmin/$', org_seafadmin, name='org_seafadmin'), + url(r'^([^/]+)/useradmin/$', org_useradmin, name='org_useradmin'), + url(r'^([^/]+)/groupadmin/$', org_group_admin, name='org_groupadmin'), +) diff --git a/organizations/utils.py b/organizations/utils.py new file mode 100644 index 0000000000..b0302dd9d5 --- /dev/null +++ b/organizations/utils.py @@ -0,0 +1,19 @@ +import sys +from django.core.cache import cache +from settings import ORG_CACHE_PREFIX + +def clear_org_ctx(request): + """ + """ + cache.delete(ORG_CACHE_PREFIX + request.user.username) + request.user.org = None + +def set_org_ctx(request, org_dict): + """ + """ + cache.set(ORG_CACHE_PREFIX + request.user.username, org_dict, sys.maxint) + request.user.org = org_dict + + + + diff --git a/organizations/views.py b/organizations/views.py new file mode 100644 index 0000000000..145dfed57d --- /dev/null +++ b/organizations/views.py @@ -0,0 +1,103 @@ +# encoding: utf-8 +import sys +from django.core.urlresolvers import reverse +from django.http import HttpResponse, HttpResponseRedirect, Http404 +from django.template import RequestContext +from django.shortcuts import render_to_response + +from auth.decorators import login_required +from pysearpc import SearpcError +from seaserv import ccnet_threaded_rpc, get_orgs_by_user, get_org_repos, \ + get_org_by_url_prefix, create_org, get_user_current_org + +from forms import OrgCreateForm +from settings import ORG_CACHE_PREFIX +from utils import set_org_ctx +from seahub.views import myhome +from seahub.utils import go_error, go_permission_error, validate_group_name + +@login_required +def create_org(request): + """ + + """ + if request.method == 'POST': + form = OrgCreateForm(request.POST) + if form.is_valid(): + org_name = form.cleaned_data['org_name'] + url_prefix = form.cleaned_data['url_prefix'] + username = request.user.username + + try: + # create_org(org_name, url_prefix, username) + ccnet_threaded_rpc.create_org(org_name, url_prefix, username) + return HttpResponseRedirect(\ + reverse(org_info, args=[url_prefix])) + except SearpcError, e: + return go_error(request, e.msg) + + else: + form = OrgCreateForm() + + return render_to_response('organizations/create_org.html', { + 'form': form, + }, context_instance=RequestContext(request)) + +@login_required +def change_account(request): + """ + + """ + orgs = get_orgs_by_user(request.user.username) + + return render_to_response('organizations/change_account.html', { + 'orgs': orgs, + }, context_instance=RequestContext(request)) + +@login_required +def org_info(request, url_prefix): + """ + """ + org = get_user_current_org(request.user.username, url_prefix) + if not org: + return HttpResponseRedirect(reverse(myhome)) + + set_org_ctx(request, org._dict) + + org_members = ccnet_threaded_rpc.get_org_emailusers(url_prefix, + 0, sys.maxint) + repos = get_org_repos(org.org_id, 0, sys.maxint) + return render_to_response('organizations/org_info.html', { + 'org': org, + 'org_users': org_members, + 'repos': repos, + }, context_instance=RequestContext(request)) + +@login_required +def org_groups(request, url_prefix): + """ + + """ + org = get_user_current_org(request.user.username, url_prefix) + if not org: + return HttpResponseRedirect(reverse(myhome)) + + if request.method == 'POST': + group_name = request.POST.get('group_name') + if not validate_group_name(group_name): + return go_error(request, u'小组名称只能包含中英文字符,数字及下划线') + + try: + group_id = ccnet_threaded_rpc.create_group(group_name.encode('utf-8'), + request.user.username) + ccnet_threaded_rpc.add_org_group(org.org_id, group_id) + except SearpcError, e: + error_msg = e.msg + return go_error(request, error_msg) + + groups = ccnet_threaded_rpc.get_org_groups(org.org_id, 0, sys.maxint) + return render_to_response('organizations/org_groups.html', { + 'org': org, + 'groups': groups, + }, context_instance=RequestContext(request)) + diff --git a/profile/templates/profile/profile_base.html b/profile/templates/profile/profile_base.html index a6bdda9cf7..16fcf438ac 100644 --- a/profile/templates/profile/profile_base.html +++ b/profile/templates/profile/profile_base.html @@ -1,4 +1,4 @@ -{% extends "myhome_base.html" %} +{% extends base_template %} {% block title %}帐号设置{% endblock %} diff --git a/profile/templates/profile/set_profile.html b/profile/templates/profile/set_profile.html index 2fadff54e5..c0d91b540c 100644 --- a/profile/templates/profile/set_profile.html +++ b/profile/templates/profile/set_profile.html @@ -2,12 +2,13 @@ {% load avatar_tags %} {% block left_panel %} - + {% endblock %} {% block right_panel %} diff --git a/settings.py b/settings.py index 4eb38130d7..c0061ddd1a 100644 --- a/settings.py +++ b/settings.py @@ -69,6 +69,7 @@ MIDDLEWARE_CLASSES = ( 'auth.middleware.AuthenticationMiddleware', 'seahub.base.middleware.InfobarMiddleware', 'seahub.subdomain.middleware.SubdomainMiddleware', + 'seahub.organizations.middleware.OrganizationMiddleware', ) SITE_ROOT_URLCONF = 'seahub.urls' @@ -93,6 +94,7 @@ TEMPLATE_CONTEXT_PROCESSORS = ( 'django.core.context_processors.request', 'django.contrib.messages.context_processors.messages', 'seahub.base.context_processors.base', + 'seahub.organizations.context_processors.org', ) @@ -105,11 +107,12 @@ INSTALLED_APPS = ( 'django.contrib.messages', 'registration', 'avatar', - 'seahub.notifications', 'seahub.base', - 'seahub.profile', 'seahub.contacts', - 'seahub.group', + 'seahub.group', + 'seahub.notifications', + 'seahub.organizations', + 'seahub.profile', 'seahub.share', 'seahub.subdomain', 'seahub.api', diff --git a/templates/base.html b/templates/base.html index 98af2b82d9..666b0693f8 100644 --- a/templates/base.html +++ b/templates/base.html @@ -30,10 +30,15 @@ {% if request.user.is_staff %} 管理员控制台 - 我的帐号 + {% block top_bar_manager_class %}{% endblock %}>管理员控制台 + {% if request.user.is_staff %} + 我的帐号 {% endif %} diff --git a/templates/error.html b/templates/error.html index a632569655..8dcc6030fc 100644 --- a/templates/error.html +++ b/templates/error.html @@ -1,4 +1,4 @@ -{% extends "myhome_base.html" %} +{% extends base_template %} {% block title %}错误{% endblock %} diff --git a/templates/org_admin_base.html b/templates/org_admin_base.html index 12c06f20b6..38d58938ae 100644 --- a/templates/org_admin_base.html +++ b/templates/org_admin_base.html @@ -4,13 +4,13 @@