1# Copyright (c) 2012-2016 Seafile Ltd.
2# -*- coding: utf-8 -*-
3# Django settings for seahub project.
4
5import sys
6import os
7import re
8
9from seaserv import FILE_SERVER_ROOT, FILE_SERVER_PORT, SERVICE_URL
10
11PROJECT_ROOT = os.path.join(os.path.dirname(__file__), os.pardir)
12
13DEBUG = False
14
15CLOUD_MODE = False
16
17ADMINS = [
18    # ('Your Name', 'your_email@domain.com'),
19]
20
21MANAGERS = ADMINS
22
23DATABASES = {
24    'default': {
25        'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
26        'NAME': '%s/seahub/seahub.db' % PROJECT_ROOT, # Or path to database file if using sqlite3.
27        'USER': '',                      # Not used with sqlite3.
28        'PASSWORD': '',                  # Not used with sqlite3.
29        'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.
30        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
31    }
32}
33
34# Local time zone for this installation. Choices can be found here:
35# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
36# although not all choices may be available on all operating systems.
37# If running in a Windows environment this must be set to the same as your
38# system time zone.
39TIME_ZONE = 'UTC'
40
41# Language code for this installation. All choices can be found here:
42# http://www.i18nguy.com/unicode/language-identifiers.html
43LANGUAGE_CODE = 'en'
44
45SITE_ID = 1
46
47# If you set this to False, Django will make some optimizations so as not
48# to load the internationalization machinery.
49USE_I18N = True
50
51# If you set this to False, Django will not format dates, numbers and
52# calendars according to the current locale.
53USE_L10N = True
54
55# If you set this to False, Django will not use timezone-aware datetimes.
56USE_TZ = False
57
58# Absolute filesystem path to the directory that will hold user-uploaded files.
59# Example: "/home/media/media.lawrence.com/media/"
60MEDIA_ROOT = '%s/media/' % PROJECT_ROOT
61
62# URL that handles the media served from MEDIA_ROOT. Make sure to use a
63# trailing slash if there is a path component (optional in other cases).
64# Examples: "http://media.lawrence.com", "http://example.com/media/"
65MEDIA_URL = '/media/'
66
67# Absolute path to the directory static files should be collected to.
68# Don't put anything in this directory yourself; store your static files
69# in apps' "static/" subdirectories and in STATICFILES_DIRS.
70# Example: "/home/media/media.lawrence.com/static/"
71STATIC_ROOT = '%s/assets/' % MEDIA_ROOT
72
73# URL prefix for static files.
74# Example: "http://media.lawrence.com/static/"
75STATIC_URL = '/media/assets/'
76
77# Additional locations of static files
78STATICFILES_DIRS = (
79    # Put strings here, like "/home/html/static" or "C:/www/django/static".
80    # Always use forward slashes, even on Windows.
81    # Don't forget to use absolute paths, not relative paths.
82    '%s/static' % PROJECT_ROOT,
83    '%s/frontend/build' % PROJECT_ROOT,
84)
85
86WEBPACK_LOADER = {
87    'DEFAULT': {
88        'BUNDLE_DIR_NAME': 'frontend/',
89        'STATS_FILE': os.path.join(PROJECT_ROOT, 'frontend/webpack-stats.pro.json'),
90    }
91}
92
93STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'
94
95# StaticI18N config
96STATICI18N_ROOT = '%s/static/scripts' % PROJECT_ROOT
97STATICI18N_OUTPUT_DIR = 'i18n'
98
99# List of finder classes that know how to find static files in
100# various locations.
101STATICFILES_FINDERS = (
102    'django.contrib.staticfiles.finders.FileSystemFinder',
103    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
104#    'django.contrib.staticfiles.finders.DefaultStorageFinder',
105)
106
107# Make this unique, and don't share it with anybody.
108SECRET_KEY = 'n*v0=jz-1rz@(4gx^tf%6^e7c&um@2)g-l=3_)t@19a69n1nv6'
109
110ENABLE_REMOTE_USER_AUTHENTICATION = False
111
112# Order is important
113MIDDLEWARE = [
114    'django.contrib.sessions.middleware.SessionMiddleware',
115    'django.middleware.locale.LocaleMiddleware',
116    'django.middleware.common.CommonMiddleware',
117    'django.middleware.csrf.CsrfViewMiddleware',
118    'django.contrib.messages.middleware.MessageMiddleware',
119    'seahub.auth.middleware.AuthenticationMiddleware',
120    'seahub.base.middleware.BaseMiddleware',
121    'seahub.base.middleware.InfobarMiddleware',
122    'seahub.password_session.middleware.CheckPasswordHash',
123    'seahub.base.middleware.ForcePasswdChangeMiddleware',
124    'termsandconditions.middleware.TermsAndConditionsRedirectMiddleware',
125    'seahub.two_factor.middleware.OTPMiddleware',
126    'seahub.two_factor.middleware.ForceTwoFactorAuthMiddleware',
127    'seahub.trusted_ip.middleware.LimitIpMiddleware'
128]
129
130SITE_ROOT_URLCONF = 'seahub.urls'
131ROOT_URLCONF = 'seahub.utils.rooturl'
132SITE_ROOT = '/'
133CSRF_COOKIE_NAME = 'sfcsrftoken'
134
135# Python dotted path to the WSGI application used by Django's runserver.
136WSGI_APPLICATION = 'seahub.wsgi.application'
137
138TEMPLATES = [
139    {
140        'BACKEND': 'django.template.backends.django.DjangoTemplates',
141        'DIRS': [
142            os.path.join(PROJECT_ROOT, '../../seahub-data/custom/templates'),
143            os.path.join(PROJECT_ROOT, 'seahub/templates'),
144        ],
145        'APP_DIRS': True,
146        'OPTIONS': {
147            'context_processors': [
148                'django.template.context_processors.i18n',
149                'django.template.context_processors.media',
150                'django.template.context_processors.static',
151                'django.template.context_processors.request',
152                'django.contrib.messages.context_processors.messages',
153
154                'seahub.auth.context_processors.auth',
155                'seahub.base.context_processors.base',
156                'seahub.base.context_processors.debug',
157            ],
158        },
159    },
160]
161
162
163LANGUAGES = [
164    # ('bg', gettext_noop(u'български език')),
165    ('ca', 'Català'),
166    ('cs', 'Čeština'),
167    ('de', 'Deutsch'),
168    ('en', 'English'),
169    ('es', 'Español'),
170    ('es-ar', 'Español de Argentina'),
171    ('es-mx', 'Español de México'),
172    ('fr', 'Français'),
173    ('it', 'Italiano'),
174    ('is', 'Íslenska'),
175    ('lv', 'Latvian'),
176    # ('mk', 'македонски јазик'),
177    ('hu', 'Magyar'),
178    ('nl', 'Nederlands'),
179    ('pl', 'Polski'),
180    ('pt-br', 'Portuguese, Brazil'),
181    ('ru', 'Русский'),
182    # ('sk', 'Slovak'),
183    ('sl', 'Slovenian'),
184    ('fi', 'Suomi'),
185    ('sv', 'Svenska'),
186    ('vi', 'Tiếng Việt'),
187    ('tr', 'Türkçe'),
188    ('uk', 'українська мова'),
189    ('he', 'עברית'),
190    ('ar', 'العربية'),
191    ('el', 'ελληνικά'),
192    ('th', 'ไทย'),
193    ('ko', '한국어'),
194    ('ja', '日本語'),
195    # ('lt', 'Lietuvių kalba'),
196    ('zh-cn', '简体中文'),
197    ('zh-tw', '繁體中文'),
198]
199
200LOCALE_PATHS = [
201    os.path.join(PROJECT_ROOT, 'locale'),
202    os.path.join(PROJECT_ROOT, 'seahub/trusted_ip/locale'),
203]
204
205INSTALLED_APPS = [
206    'django.contrib.contenttypes',
207    'django.contrib.sessions',
208    'django.contrib.messages',
209    'django.contrib.staticfiles',
210
211    # In order to overide command `createsuperuser`, base app *must* before auth app.
212    # ref: https://docs.djangoproject.com/en/1.11/howto/custom-management-commands/#overriding-commands
213    'seahub.base',
214    'django.contrib.auth',
215
216    'registration',
217    'captcha',
218    'statici18n',
219    'constance',
220    'constance.backends.database',
221    'termsandconditions',
222    'webpack_loader',
223
224    'seahub.api2',
225    'seahub.avatar',
226    'seahub.contacts',
227    'seahub.drafts',
228    'seahub.institutions',
229    'seahub.invitations',
230    'seahub.wiki',
231    'seahub.group',
232    'seahub.notifications',
233    'seahub.options',
234    'seahub.onlyoffice',
235    'seahub.profile',
236    'seahub.share',
237    'seahub.help',
238    'seahub.thumbnail',
239    'seahub.password_session',
240    'seahub.admin_log',
241    'seahub.wopi',
242    'seahub.tags',
243    'seahub.revision_tag',
244    'seahub.two_factor',
245    'seahub.role_permissions',
246    'seahub.trusted_ip',
247    'seahub.repo_tags',
248    'seahub.file_tags',
249    'seahub.related_files',
250    'seahub.work_weixin',
251    'seahub.dingtalk',
252    'seahub.file_participants',
253    'seahub.repo_api_tokens',
254    'seahub.abuse_reports',
255    'seahub.repo_auto_delete',
256    'seahub.ocm',
257]
258
259
260# Enable or disable view File Scan
261# ENABLE_FILE_SCAN = True
262
263# Enable or disable multiple storage backends.
264ENABLE_STORAGE_CLASSES = False
265
266# `USER_SELECT` or `ROLE_BASED` or `REPO_ID_MAPPING`
267STORAGE_CLASS_MAPPING_POLICY = 'USER_SELECT'
268
269# Enable or disable constance(web settings).
270ENABLE_SETTINGS_VIA_WEB = True
271CONSTANCE_BACKEND = 'constance.backends.database.DatabaseBackend'
272CONSTANCE_DATABASE_CACHE_BACKEND = 'default'
273
274AUTHENTICATION_BACKENDS = (
275    'seahub.base.accounts.AuthBackend',
276)
277
278ENABLE_OAUTH = False
279ENABLE_WATERMARK = False
280
281ENABLE_SHOW_CONTACT_EMAIL_WHEN_SEARCH_USER = False
282
283# enable work weixin
284ENABLE_WORK_WEIXIN = False
285
286# enable weixin
287ENABLE_WEIXIN = False
288
289# enable dingtalk
290ENABLE_DINGTALK = False
291
292# allow user to clean library trash
293ENABLE_USER_CLEAN_TRASH = True
294
295LOGIN_REDIRECT_URL = '/'
296LOGIN_URL = '/accounts/login/'
297LOGIN_ERROR_DETAILS = False
298LOGOUT_REDIRECT_URL = None
299
300ACCOUNT_ACTIVATION_DAYS = 7
301
302# allow seafile amdin view user's repo
303ENABLE_SYS_ADMIN_VIEW_REPO = False
304
305#allow search from LDAP directly during auto-completion (not only search imported users)
306ENABLE_SEARCH_FROM_LDAP_DIRECTLY = False
307
308# show traffic on the UI
309SHOW_TRAFFIC = True
310
311# show or hide library 'download' button
312SHOW_REPO_DOWNLOAD_BUTTON = False
313
314# enable 'upload folder' or not
315ENABLE_UPLOAD_FOLDER = True
316
317# enable resumable fileupload or not
318ENABLE_RESUMABLE_FILEUPLOAD = False
319RESUMABLE_UPLOAD_FILE_BLOCK_SIZE = 8
320
321## maxNumberOfFiles for fileupload
322MAX_NUMBER_OF_FILES_FOR_FILEUPLOAD = 1000
323
324# enable encrypt library
325ENABLE_ENCRYPTED_LIBRARY = True
326ENCRYPTED_LIBRARY_VERSION = 2
327
328# enable reset encrypt library's password when user forget password
329ENABLE_RESET_ENCRYPTED_REPO_PASSWORD = False
330
331# mininum length for password of encrypted library
332REPO_PASSWORD_MIN_LENGTH = 8
333
334# token length for the share link
335SHARE_LINK_TOKEN_LENGTH = 20
336
337# if limit only authenticated user can view preview share link
338SHARE_LINK_LOGIN_REQUIRED = False
339
340# min/max expire days for a share link
341SHARE_LINK_EXPIRE_DAYS_MIN = 0 # 0 means no limit
342SHARE_LINK_EXPIRE_DAYS_MAX = 0 # 0 means no limit
343
344# default expire days should be
345# greater than or equal to MIN and less than or equal to MAX
346SHARE_LINK_EXPIRE_DAYS_DEFAULT = 0
347
348# min/max expire days for an upload link
349UPLOAD_LINK_EXPIRE_DAYS_MIN = 0 # 0 means no limit
350UPLOAD_LINK_EXPIRE_DAYS_MAX = 0 # 0 means no limit
351
352# default expire days should be
353# greater than or equal to MIN and less than or equal to MAX
354UPLOAD_LINK_EXPIRE_DAYS_DEFAULT = 0
355
356# mininum length for the password of a share link
357SHARE_LINK_PASSWORD_MIN_LENGTH = 8
358
359# enable or disable share link audit
360ENABLE_SHARE_LINK_AUDIT = False
361
362# enable or disable report abuse file on share link page
363ENABLE_SHARE_LINK_REPORT_ABUSE = False
364
365# share link audit code timeout
366SHARE_LINK_AUDIT_CODE_TIMEOUT = 60 * 60
367
368# enable or disable limit ip
369ENABLE_LIMIT_IPADDRESS = False
370TRUSTED_IP_LIST = ['127.0.0.1']
371
372# Control the language that send email. Default to user's current language.
373SHARE_LINK_EMAIL_LANGUAGE = ''
374
375# check virus for files uploaded form upload link
376ENABLE_UPLOAD_LINK_VIRUS_CHECK = False
377
378# mininum length for user's password
379USER_PASSWORD_MIN_LENGTH = 6
380
381# LEVEL based on four types of input:
382# num, upper letter, lower letter, other symbols
383# '3' means password must have at least 3 types of the above.
384USER_PASSWORD_STRENGTH_LEVEL = 3
385
386# default False, only check USER_PASSWORD_MIN_LENGTH
387# when True, check password strength level, STRONG(or above) is allowed
388USER_STRONG_PASSWORD_REQUIRED = False
389
390# Force user to change password when admin add/reset a user.
391FORCE_PASSWORD_CHANGE = True
392
393# Enable a user to change password in 'settings' page.
394ENABLE_CHANGE_PASSWORD = True
395
396# Enable a user to get auth token in 'settings' page.
397ENABLE_GET_AUTH_TOKEN_BY_SESSION = False
398
399ENABLE_DELETE_ACCOUNT = True
400ENABLE_UPDATE_USER_INFO = True
401
402# Enable or disable repo history setting
403ENABLE_REPO_HISTORY_SETTING = True
404
405# Enable or disable org repo creation by user
406ENABLE_USER_CREATE_ORG_REPO = True
407
408DISABLE_SYNC_WITH_ANY_FOLDER = False
409
410ENABLE_TERMS_AND_CONDITIONS = False
411
412# Enable or disable sharing to all groups
413ENABLE_SHARE_TO_ALL_GROUPS = False
414
415# Enable or disable sharing to departments
416ENABLE_SHARE_TO_DEPARTMENT = True
417
418# interval for request unread notifications
419UNREAD_NOTIFICATIONS_REQUEST_INTERVAL = 3 * 60 # seconds
420
421# Enable file comments
422ENABLE_FILE_COMMENT = True
423
424# Enable seafile docs
425ENABLE_SEAFILE_DOCS = False
426
427# File preview
428FILE_PREVIEW_MAX_SIZE = 30 * 1024 * 1024
429FILE_ENCODING_LIST = ['auto', 'utf-8', 'gbk', 'ISO-8859-1', 'ISO-8859-5']
430FILE_ENCODING_TRY_LIST = ['utf-8', 'gbk']
431HIGHLIGHT_KEYWORD = False # If True, highlight the keywords in the file when the visit is via clicking a link in 'search result' page.
432# extensions of previewed files
433TEXT_PREVIEW_EXT = """ac, am, bat, c, cc, cmake, cpp, cs, css, diff, el, h, html, htm, java, js, json, less, make, org, php, pl, properties, py, rb, scala, script, sh, sql, txt, text, tex, vi, vim, xhtml, xml, log, csv, groovy, rst, patch, go, yml"""
434
435# Common settings(file extension, storage) for avatar and group avatar.
436AVATAR_FILE_STORAGE = '' # Replace with 'seahub.base.database_storage.DatabaseStorage' if save avatar files to database
437AVATAR_ALLOWED_FILE_EXTS = ('.jpg', '.png', '.jpeg', '.gif')
438# Avatar
439AVATAR_STORAGE_DIR = 'avatars'
440AVATAR_HASH_USERDIRNAMES = True
441AVATAR_HASH_FILENAMES = True
442AVATAR_GRAVATAR_BACKUP = False
443AVATAR_DEFAULT_URL = '/avatars/default.png'
444AVATAR_DEFAULT_NON_REGISTERED_URL = '/avatars/default-non-register.jpg'
445AVATAR_MAX_AVATARS_PER_USER = 1
446AVATAR_CACHE_TIMEOUT = 14 * 24 * 60 * 60
447AUTO_GENERATE_AVATAR_SIZES = (16, 20, 24, 28, 32, 36, 40, 42, 48, 60, 64, 72, 80, 84, 96, 128, 160)
448# Group avatar
449GROUP_AVATAR_STORAGE_DIR = 'avatars/groups'
450GROUP_AVATAR_DEFAULT_URL = 'avatars/groups/default.png'
451AUTO_GENERATE_GROUP_AVATAR_SIZES = (20, 24, 32, 36, 48, 56)
452
453LOG_DIR = os.environ.get('SEAHUB_LOG_DIR', '/tmp')
454CACHE_DIR = "/tmp"
455install_topdir = os.path.expanduser(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
456central_conf_dir = os.environ.get('SEAFILE_CENTRAL_CONF_DIR', '')
457
458CACHES = {
459    'default': {
460        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
461        'LOCATION': os.path.join(CACHE_DIR, 'seahub_cache'),
462        'OPTIONS': {
463            'MAX_ENTRIES': 1000000
464        }
465    },
466
467    # Compatible with existing `COMPRESS_CACHE_BACKEND` setting after
468    # upgrading to django-compressor v2.2.
469    # ref: https://manual.seafile.com/deploy_pro/deploy_in_a_cluster.html
470    'django.core.cache.backends.locmem.LocMemCache': {
471        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
472    },
473}
474
475# rest_framwork
476REST_FRAMEWORK = {
477    'DEFAULT_RENDERER_CLASSES': [
478        'rest_framework.renderers.JSONRenderer',
479    ],
480    'DEFAULT_THROTTLE_RATES': {
481        'ping': '3000/minute',
482        'anon': '60/minute',
483        'user': '3000/minute',
484    },
485    # https://github.com/tomchristie/django-rest-framework/issues/2891
486    'UNICODE_JSON': False,
487}
488REST_FRAMEWORK_THROTTING_WHITELIST = []
489
490# file and path
491GET_FILE_HISTORY_TIMEOUT = 10 * 60 # seconds
492MAX_UPLOAD_FILE_NAME_LEN    = 255
493MAX_FILE_NAME 		    = MAX_UPLOAD_FILE_NAME_LEN
494MAX_PATH 		    = 4096
495
496FILE_LOCK_EXPIRATION_DAYS = 0
497
498# Whether or not activate user when registration complete.
499# If set to ``False``, new user will be activated by admin or via activate link.
500ACTIVATE_AFTER_REGISTRATION = True
501# Whether or not send activation Email to user when registration complete.
502# This option will be ignored if ``ACTIVATE_AFTER_REGISTRATION`` set to ``True``.
503REGISTRATION_SEND_MAIL = False
504
505# Whether or not send notify email to sytem admins when user registered or
506# first login through Shibboleth.
507NOTIFY_ADMIN_AFTER_REGISTRATION = False
508
509# Whether or not activate inactive user on first login. Mainly used in LDAP user sync.
510ACTIVATE_AFTER_FIRST_LOGIN = False
511
512REQUIRE_DETAIL_ON_REGISTRATION = False
513
514# Account initial password, for password resetting.
515# INIT_PASSWD can either be a string, or a function (function has to be set without the brackets)
516def genpassword():
517    from django.utils.crypto import get_random_string
518    return get_random_string(10)
519INIT_PASSWD = genpassword
520
521# browser tab title
522SITE_TITLE = 'Private Seafile'
523
524# Base name used in email sending
525SITE_NAME = 'Seafile'
526
527# Path to the license file(relative to the media path)
528LICENSE_PATH = os.path.join(PROJECT_ROOT, '../../seafile-license.txt')
529
530# Path to the background image file of login page(relative to the media path)
531LOGIN_BG_IMAGE_PATH = 'img/login-bg.jpg'
532
533# Path to the favicon file (relative to the media path)
534# tip: use a different name when modify it.
535FAVICON_PATH = 'img/favicon.ico'
536
537# Path to the Logo Imagefile (relative to the media path)
538LOGO_PATH = 'img/seafile-logo.png'
539# logo size. the unit is 'px'
540LOGO_WIDTH = ''
541LOGO_HEIGHT = 32
542
543CUSTOM_LOGO_PATH = 'custom/mylogo.png'
544CUSTOM_FAVICON_PATH = 'custom/favicon.ico'
545CUSTOM_LOGIN_BG_PATH = 'custom/login-bg.jpg'
546
547# used before version 6.3: the relative path of css file under seahub-data (e.g. custom/custom.css)
548BRANDING_CSS = ''
549
550# used in 6.3+, enable setting custom css via admin web interface
551ENABLE_BRANDING_CSS = False
552
553# Using Django to server static file. Set to `False` if deployed behide a web
554# server.
555SERVE_STATIC = True
556
557# Enable or disable registration on web.
558ENABLE_SIGNUP = False
559
560# show 'log out' icon in top-bar or not.
561SHOW_LOGOUT_ICON = False
562
563# privacy policy link and service link
564PRIVACY_POLICY_LINK = ''
565TERMS_OF_SERVICE_LINK = ''
566
567# For security consideration, please set to match the host/domain of your site, e.g., ALLOWED_HOSTS = ['.example.com'].
568# Please refer https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts for details.
569ALLOWED_HOSTS = ['*']
570
571# Logging
572LOGGING = {
573    'version': 1,
574
575    # Enable existing loggers so that gunicorn errors will be bubbled up when
576    # server side error page "Internal Server Error" occurs.
577    # ref: https://www.caktusgroup.com/blog/2015/01/27/Django-Logging-Configuration-logging_config-default-settings-logger/
578    'disable_existing_loggers': False,
579
580    'formatters': {
581        'standard': {
582            'format': '%(asctime)s [%(levelname)s] %(name)s:%(lineno)s %(funcName)s %(message)s'
583        },
584    },
585    'filters': {
586        'require_debug_false': {
587            '()': 'django.utils.log.RequireDebugFalse'
588        },
589        'require_debug_true': {
590            '()': 'django.utils.log.RequireDebugTrue'
591        },
592    },
593    'handlers': {
594        'console': {
595            'level': 'DEBUG',
596            'filters': ['require_debug_true'],
597            'class': 'logging.StreamHandler',
598            'formatter': 'standard',
599        },
600        'default': {
601            'level': 'INFO',
602            'class': 'logging.handlers.RotatingFileHandler',
603            'filename': os.path.join(LOG_DIR, 'seahub.log'),
604            'maxBytes': 1024*1024*100,  # 100 MB
605            'backupCount': 5,
606            'formatter': 'standard',
607        },
608        'onlyoffice_handler': {
609            'level': 'INFO',
610            'class': 'logging.handlers.RotatingFileHandler',
611            'filename': os.path.join(LOG_DIR, 'onlyoffice.log'),
612            'maxBytes': 1024*1024*100,  # 100 MB
613            'backupCount': 5,
614            'formatter': 'standard',
615        },
616        'mail_admins': {
617            'level': 'ERROR',
618            'filters': ['require_debug_false'],
619            'class': 'django.utils.log.AdminEmailHandler'
620        }
621    },
622    'loggers': {
623        '': {
624            'handlers': ['default'],
625            'level': 'INFO',
626            'propagate': True
627        },
628        'django.request': {
629            'handlers': ['default', 'mail_admins'],
630            'level': 'INFO',
631            'propagate': False
632        },
633        'py.warnings': {
634            'handlers': ['console', ],
635            'level': 'INFO',
636            'propagate': False
637        },
638        'onlyoffice': {
639            'handlers': ['onlyoffice_handler', ],
640            'level': 'INFO',
641            'propagate': False
642        },
643    }
644}
645
646#Login Attempt
647LOGIN_ATTEMPT_LIMIT = 5
648LOGIN_ATTEMPT_TIMEOUT = 15 * 60 # in seconds (default: 15 minutes)
649FREEZE_USER_ON_LOGIN_FAILED = False # deactivate user account when login attempts exceed limit
650
651# Age of cookie, in seconds (default: 1 day).
652SESSION_COOKIE_AGE = 24 * 60 * 60
653
654# Days of remembered login info (deafult: 7 days)
655LOGIN_REMEMBER_DAYS = 7
656
657SEAFILE_VERSION = '8.0.7'
658
659CAPTCHA_IMAGE_SIZE = (90, 42)
660
661###################
662# Image Thumbnail #
663###################
664
665# Enable or disable thumbnail
666ENABLE_THUMBNAIL = True
667
668# Absolute filesystem path to the directory that will hold thumbnail files.
669SEAHUB_DATA_ROOT = os.path.join(PROJECT_ROOT, '../../seahub-data')
670if os.path.exists(SEAHUB_DATA_ROOT):
671    THUMBNAIL_ROOT = os.path.join(SEAHUB_DATA_ROOT, 'thumbnail')
672else:
673    THUMBNAIL_ROOT = os.path.join(PROJECT_ROOT, 'seahub/thumbnail/thumb')
674
675THUMBNAIL_EXTENSION = 'png'
676
677# for thumbnail: height(px) and width(px)
678THUMBNAIL_DEFAULT_SIZE = 48
679THUMBNAIL_SIZE_FOR_GRID = 192
680THUMBNAIL_SIZE_FOR_ORIGINAL = 1024
681
682# size(MB) limit for generate thumbnail
683THUMBNAIL_IMAGE_SIZE_LIMIT = 30
684THUMBNAIL_IMAGE_ORIGINAL_SIZE_LIMIT = 256
685
686# video thumbnails
687ENABLE_VIDEO_THUMBNAIL = False
688THUMBNAIL_VIDEO_FRAME_TIME = 5  # use the frame at 5 second as thumbnail
689
690# template for create new office file
691OFFICE_TEMPLATE_ROOT = os.path.join(MEDIA_ROOT, 'office-template')
692
693ENABLE_WEBDAV_SECRET = False
694ENABLE_USER_SET_CONTACT_EMAIL = False
695
696#####################
697# Global AddressBook #
698#####################
699ENABLE_GLOBAL_ADDRESSBOOK = True
700ENABLE_ADDRESSBOOK_OPT_IN = False
701
702#####################
703# Folder Permission #
704#####################
705ENABLE_FOLDER_PERM = False
706
707####################
708# Guest Invite     #
709####################
710ENABLE_GUEST_INVITATION = False
711INVITATION_ACCEPTER_BLACKLIST = []
712
713########################
714# Security Enhancements #
715########################
716
717ENABLE_SUDO_MODE = True
718FILESERVER_TOKEN_ONCE_ONLY = True
719
720#################
721# Email sending #
722#################
723
724SEND_EMAIL_ON_ADDING_SYSTEM_MEMBER = True # Whether to send email when a system staff adding new member.
725SEND_EMAIL_ON_RESETTING_USER_PASSWD = True # Whether to send email when a system staff resetting user's password.
726
727##########################
728# Settings for Extra App #
729##########################
730
731##########################
732# Settings for frontend  #
733##########################
734
735SEAFILE_COLLAB_SERVER = ''
736
737##########################
738# Settings for dtable web  #
739##########################
740
741DTABLE_WEB_SERVER = ''
742
743############################
744# Settings for Seahub Priv #
745############################
746
747# Replace from email to current user instead of email sender.
748REPLACE_FROM_EMAIL = False
749
750# Add ``Reply-to`` header, see RFC #822.
751ADD_REPLY_TO_HEADER = False
752
753ENABLE_DEMO_USER = False
754CLOUD_DEMO_USER = 'demo@seafile.com'
755
756ENABLE_TWO_FACTOR_AUTH = False
757OTP_LOGIN_URL = '/profile/two_factor_authentication/setup/'
758TWO_FACTOR_DEVICE_REMEMBER_DAYS = 90
759ENABLE_FORCE_2FA_TO_ALL_USERS = False
760
761# Enable wiki
762ENABLE_WIKI = True
763
764# Enable 'repo snapshot label' feature
765ENABLE_REPO_SNAPSHOT_LABEL = False
766
767#  Repo wiki mode
768ENABLE_REPO_WIKI_MODE = True
769
770############################
771# HU berlin additional #
772############################
773
774# ADDITIONAL_SHARE_DIALOG_NOTE = {
775#     'title': 'Attention! Read before shareing files:',
776#     'content': 'Do not share personal or confidential official data with **.'
777# }
778ADDITIONAL_SHARE_DIALOG_NOTE = None
779
780# ADDITIONAL_APP_BOTTOM_LINKS = {
781#     'seafile': 'http://dev.seahub.com/seahub',
782#     'dtable-web': 'http://dev.seahub.com/dtable-web'
783# }
784ADDITIONAL_APP_BOTTOM_LINKS = None
785
786# ADDITIONAL_ABOUT_DIALOG_LINKS = {
787#     'seafile': 'http://dev.seahub.com/seahub',
788#     'dtable-web': 'http://dev.seahub.com/dtable-web'
789# }
790ADDITIONAL_ABOUT_DIALOG_LINKS = None
791
792############################
793# Settings for SeafileDocs #
794############################
795if os.environ.get('SEAFILE_DOCS', None):
796    LOGO_PATH = 'img/seafile-docs-logo.png'
797    LOGO_WIDTH = ''
798    ENABLE_WIKI = True
799
800d = os.path.dirname
801EVENTS_CONFIG_FILE = os.environ.get(
802    'EVENTS_CONFIG_FILE',
803    os.path.join(
804        d(d(d(d(os.path.abspath(__file__))))), 'conf', 'seafevents.conf'
805    )
806)
807
808del d
809if not os.path.exists(EVENTS_CONFIG_FILE):
810    del EVENTS_CONFIG_FILE
811
812#####################
813# External settings #
814#####################
815
816def load_local_settings(module):
817    '''Import any symbols that begin with A-Z. Append to lists any symbols
818    that begin with "EXTRA_".
819
820    '''
821    if hasattr(module, 'HTTP_SERVER_ROOT'):
822        if not hasattr(module, 'FILE_SERVER_ROOT'):
823            module.FILE_SERVER_ROOT = module.HTTP_SERVER_ROOT
824        del module.HTTP_SERVER_ROOT
825    for attr in dir(module):
826        match = re.search('^EXTRA_(\w+)', attr)
827        if match:
828            name = match.group(1)
829            value = getattr(module, attr)
830            try:
831                globals()[name] += value
832            except KeyError:
833                globals()[name] = value
834        elif re.search('^[A-Z]', attr):
835            globals()[attr] = getattr(module, attr)
836
837
838# Load seahub_extra_settings.py
839try:
840    from seahub_extra import seahub_extra_settings
841except ImportError:
842    pass
843else:
844    load_local_settings(seahub_extra_settings)
845    del seahub_extra_settings
846
847# Load local_settings.py
848try:
849    import seahub.local_settings
850except ImportError:
851    pass
852else:
853    load_local_settings(seahub.local_settings)
854    del seahub.local_settings
855
856# Load seahub_settings.py in server release
857try:
858    if os.path.exists(central_conf_dir):
859        sys.path.insert(0, central_conf_dir)
860    import seahub_settings
861except ImportError:
862    pass
863else:
864    # In server release, sqlite3 db file is <topdir>/seahub.db
865    DATABASES['default']['NAME'] = os.path.join(install_topdir, 'seahub.db')
866
867    # In server release, gunicorn is used to deploy seahub
868    INSTALLED_APPS.append('gunicorn')
869
870    load_local_settings(seahub_settings)
871    del seahub_settings
872
873# Remove install_topdir from path
874sys.path.pop(0)
875
876# Following settings are private, can not be overwrite.
877INNER_FILE_SERVER_ROOT = 'http://127.0.0.1:' + FILE_SERVER_PORT
878
879CONSTANCE_ENABLED = ENABLE_SETTINGS_VIA_WEB
880CONSTANCE_CONFIG = {
881    'SERVICE_URL': (SERVICE_URL, ''),
882    'FILE_SERVER_ROOT': (FILE_SERVER_ROOT, ''),
883    'DISABLE_SYNC_WITH_ANY_FOLDER': (DISABLE_SYNC_WITH_ANY_FOLDER, ''),
884
885    'ENABLE_SIGNUP': (ENABLE_SIGNUP, ''),
886    'ACTIVATE_AFTER_REGISTRATION': (ACTIVATE_AFTER_REGISTRATION, ''),
887    'REGISTRATION_SEND_MAIL': (REGISTRATION_SEND_MAIL, ''),
888    'LOGIN_REMEMBER_DAYS': (LOGIN_REMEMBER_DAYS, ''),
889    'LOGIN_ATTEMPT_LIMIT': (LOGIN_ATTEMPT_LIMIT, ''),
890    'FREEZE_USER_ON_LOGIN_FAILED': (FREEZE_USER_ON_LOGIN_FAILED, ''),
891
892    'ENABLE_USER_CREATE_ORG_REPO': (ENABLE_USER_CREATE_ORG_REPO, ''),
893
894    'ENABLE_ENCRYPTED_LIBRARY': (ENABLE_ENCRYPTED_LIBRARY, ''),
895    'REPO_PASSWORD_MIN_LENGTH': (REPO_PASSWORD_MIN_LENGTH, ''),
896    'ENABLE_REPO_HISTORY_SETTING': (ENABLE_REPO_HISTORY_SETTING, ''),
897    'FORCE_PASSWORD_CHANGE': (FORCE_PASSWORD_CHANGE, ''),
898
899    'USER_STRONG_PASSWORD_REQUIRED': (USER_STRONG_PASSWORD_REQUIRED, ''),
900    'USER_PASSWORD_MIN_LENGTH': (USER_PASSWORD_MIN_LENGTH, ''),
901    'USER_PASSWORD_STRENGTH_LEVEL': (USER_PASSWORD_STRENGTH_LEVEL, ''),
902
903    'SHARE_LINK_TOKEN_LENGTH': (SHARE_LINK_TOKEN_LENGTH, ''),
904    'SHARE_LINK_PASSWORD_MIN_LENGTH': (SHARE_LINK_PASSWORD_MIN_LENGTH, ''),
905    'ENABLE_TWO_FACTOR_AUTH': (ENABLE_TWO_FACTOR_AUTH, ''),
906
907    'TEXT_PREVIEW_EXT': (TEXT_PREVIEW_EXT, ''),
908    'ENABLE_SHARE_TO_ALL_GROUPS': (ENABLE_SHARE_TO_ALL_GROUPS, ''),
909
910    'SITE_NAME': (SITE_NAME, ''),
911    'SITE_TITLE': (SITE_TITLE, ''),
912
913    'ENABLE_BRANDING_CSS': (ENABLE_BRANDING_CSS, ''),
914    'CUSTOM_CSS': ('', ''),
915
916    'ENABLE_TERMS_AND_CONDITIONS': (ENABLE_TERMS_AND_CONDITIONS, ''),
917    'ENABLE_USER_CLEAN_TRASH': (ENABLE_USER_CLEAN_TRASH, ''),
918}
919
920# if Seafile admin enable remote user authentication in conf/seahub_settings.py
921# then add 'seahub.auth.middleware.SeafileRemoteUserMiddleware' and
922# 'seahub.auth.backends.SeafileRemoteUserBackend' to settings.
923if ENABLE_REMOTE_USER_AUTHENTICATION:
924    MIDDLEWARE.append('seahub.auth.middleware.SeafileRemoteUserMiddleware')
925    AUTHENTICATION_BACKENDS += ('seahub.auth.backends.SeafileRemoteUserBackend',)
926
927if ENABLE_OAUTH or ENABLE_WORK_WEIXIN or ENABLE_WEIXIN or ENABLE_DINGTALK:
928    AUTHENTICATION_BACKENDS += ('seahub.oauth.backends.OauthRemoteUserBackend',)
929
930#####################
931# Custom Nav Items  #
932#####################
933# an example:
934# CUSTOM_NAV_ITEMS = [
935#     {'icon': 'sf2-icon-star',
936#      'desc': 'test custom name',
937#      'link': 'http://127.0.0.1:8000/shared-libs/',
938#      },
939# ]
940