Better frequent questions, tiny css improvements

master
Alice 5 years ago
parent 5cf77af233
commit 2fc3a0274c

@ -40,13 +40,16 @@ INSTALLED_APPS = (
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.humanize',
'django_countries',
'lambdainst',
'payments',
'tickets',
'downloads',
'kb',
'constance',
'constance.backends.database',
'tinymce',
)
MIDDLEWARE = (
@ -274,6 +277,7 @@ CONSTANCE_CONFIG = {
'TRIAL_PERIOD_MAX': (84, "Maximum number of trial periods to give (84*2h=1w)"),
'NOTIFY_DAYS_BEFORE': ("3, 1", "When to send account expiration notifications. In number of days before, separated y commas",
'integer_list'),
'KB_MAX_TOP_ENTRIES': (10, "Maximum number of categories to show in the short list"),
}
CONSTANCE_ADDITIONAL_FIELDS = {
@ -282,6 +286,22 @@ CONSTANCE_ADDITIONAL_FIELDS = {
}],
}
TINYMCE_DEFAULT_CONFIG = {
'selector': 'textarea',
'theme': 'modern',
'plugins': 'link image preview codesample table code lists paste',
'toolbar1': 'bold italic underline | alignleft aligncenter alignright alignjustify '
'| bullist numlist | outdent indent | table | link image | codesample | preview code',
'contextmenu': 'formats | link image',
'menubar': False,
'inline': False,
'statusbar': True,
'height': 360,
'width': 'auto',
'paste_as_text': True,
'browser_spellcheck': True,
}
# Local settings
try:

@ -1,6 +1,7 @@
from django.urls import path, include
from django.contrib import admin
from django.contrib.auth import views as auth_views
from django.views.generic.base import RedirectView
from lambdainst import views as account_views
@ -18,6 +19,7 @@ urlpatterns = [
path('ca.crt', account_views.ca_crt),
path('setlang', views.set_lang, name='set_lang'),
path('chat', views.chat, name='chat'),
path('page/faq', RedirectView.as_view(url='/kb/')),
path('page/<name>', views.page, name='page'),
path('status', account_views.status),
@ -30,8 +32,10 @@ urlpatterns = [
path('account/reset/done/', auth_views.PasswordResetCompleteView.as_view(),
name='password_reset_complete'),
path('tinymce/', include('tinymce.urls')),
path('account/', include('lambdainst.urls', namespace='account')),
path('payments/', include('payments.urls', namespace='payments')),
path('tickets/', include('tickets.urls', namespace='tickets')),
path('kb/', include('kb.urls', namespace='kb')),
]

@ -0,0 +1,48 @@
from django.contrib import admin
from django_admin_listfilter_dropdown.filters import DropdownFilter
from .models import KbCategory, KbCategoryName, KbCategoryDescription
from .models import KbEntry, KbEntryAnswer, KbEntryQuestion
def custom_titled_filter(title, c=admin.FieldListFilter):
class Wrapper(c):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.title = title
return Wrapper
class KbCategoryNameInline(admin.TabularInline):
model = KbCategoryName
extra = 0
class KbCategoryDescriptionInline(admin.TabularInline):
model = KbCategoryDescription
extra = 0
class KbCategoryAdmin(admin.ModelAdmin):
list_display = ('slug', 'name', 'entries')
inlines = (KbCategoryNameInline, KbCategoryDescriptionInline)
def entries(self, instance):
return instance.entry_set.count()
class KbEntryQuestionInline(admin.TabularInline):
model = KbEntryQuestion
extra = 0
class KbEntryAnswerInline(admin.StackedInline):
model = KbEntryAnswer
extra = 0
class KbEntryAdmin(admin.ModelAdmin):
list_display = ('category', 'title', 'question', 'score', 'internal')
list_filter = ('category', 'internal')
search_fields = ('category', 'title', 'question', 'answer')
inlines = (KbEntryQuestionInline, KbEntryAnswerInline)
def score(self, instance):
return "%d (%d votes)" % (instance.get_score(), instance.get_vote_count())
admin.site.register(KbCategory, KbCategoryAdmin)
admin.site.register(KbEntry, KbEntryAdmin)

@ -0,0 +1,5 @@
from django.apps import AppConfig
class HelpConfig(AppConfig):
name = 'help'

@ -0,0 +1,93 @@
# Generated by Django 2.2.1 on 2019-10-22 13:15
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import tinymce.models
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='KbCategory',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('slug', models.SlugField()),
('internal_name', models.CharField(max_length=100, verbose_name='Internal name')),
],
options={
'verbose_name': 'Knowledgebase Category',
'verbose_name_plural': 'Knowledgebase Categories',
},
),
migrations.CreateModel(
name='KbEntry',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('create_date', models.DateTimeField(auto_now_add=True)),
('title', models.CharField(max_length=50)),
('internal', models.BooleanField(default=False)),
('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='entry_set', to='kb.KbCategory')),
],
options={
'verbose_name': 'Knowledgebase Entry',
'verbose_name_plural': 'Knowledgebase Entries',
},
),
migrations.CreateModel(
name='KbEntryVote',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('create_date', models.DateTimeField(auto_now_add=True)),
('vote', models.IntegerField()),
('entry', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='vote_set', to='kb.KbEntry')),
('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'Knowledgebase Entry Vote',
},
),
migrations.CreateModel(
name='KbEntryQuestion',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('language', models.CharField(max_length=2)),
('question', models.CharField(max_length=200)),
('entry', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='question_set', to='kb.KbEntry')),
],
),
migrations.CreateModel(
name='KbEntryAnswer',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('language', models.CharField(max_length=2)),
('answer', tinymce.models.HTMLField()),
('entry', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answer_set', to='kb.KbEntry')),
],
),
migrations.CreateModel(
name='KbCategoryName',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('language', models.CharField(max_length=2)),
('name', models.CharField(max_length=100)),
('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='name_set', to='kb.KbCategory')),
],
),
migrations.CreateModel(
name='KbCategoryDescription',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('language', models.CharField(max_length=2)),
('description', models.TextField()),
('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='description_set', to='kb.KbCategory')),
],
),
]

@ -0,0 +1,136 @@
from django.db import models
from django.db.models.aggregates import Sum
from django.conf import settings
from django.urls import reverse
from django.template.loader import render_to_string
from django.dispatch import receiver
from django.utils.translation import get_language
from constance import config
from tinymce import HTMLField
def get_internationalized(obj_set, prop_name):
obj = obj_set.filter(language=get_language()).first()
if obj:
return getattr(obj, prop_name)
return ""
class KbCategory(models.Model):
slug = models.SlugField()
internal_name = models.CharField("Internal name", max_length=100)
def get_absolute_url(self):
return reverse('help:kb_category', kwargs=dict(category=self.slug))
def get_top_entries(self, n=None):
n = n or config.KB_MAX_TOP_ENTRIES
return KbEntry.objects.get_top(n, category=self)
def get_entry_count(self):
return self.entry_set.filter(internal=False).count()
def __str__(self):
return self.name
@property
def name(self):
return get_internationalized(self.name_set, 'name')
@property
def description(self):
return get_internationalized(self.description_set, 'description')
class Meta:
verbose_name = "Knowledgebase Category"
verbose_name_plural = "Knowledgebase Categories"
class KbCategoryName(models.Model):
category = models.ForeignKey(KbCategory, on_delete=models.CASCADE,
related_name='name_set')
language = models.CharField(max_length=2)
name = models.CharField(max_length=100)
class KbCategoryDescription(models.Model):
category = models.ForeignKey(KbCategory, on_delete=models.CASCADE,
related_name='description_set')
language = models.CharField(max_length=2)
description = models.TextField()
class KbEntry(models.Model):
create_date = models.DateTimeField(auto_now_add=True, editable=False)
category = models.ForeignKey(KbCategory, on_delete=models.CASCADE,
related_name='entry_set')
title = models.CharField(max_length=50)
internal = models.BooleanField(default=False)
def vote(self, user, v):
vote = self.vote_set.filter(user=user).first()
if vote:
if vote.vote == v:
return
vote.vote = v
vote.save()
else:
v = KbEntryVote(entry=self, user=user, vote=v)
v.save()
def get_score(self):
return self.vote_set.aggregate(Sum('vote'))['vote__sum'] or 0
def get_vote_count(self):
return self.vote_set.count()
def get_absolute_url(self):
return reverse('help:kb_entry', kwargs=dict(category=self.category.slug, entry=self.id))
@property
def question(self):
return self.question_set.filter(language=get_language()).first().question
@property
def answer(self):
return self.answer_set.filter(language=get_language()).first().answer
def __str__(self):
return self.question
class Meta:
verbose_name = "Knowledgebase Entry"
verbose_name_plural = "Knowledgebase Entries"
class KbEntryManager(models.Manager):
def get_top(self, n, **kwargs):
return (self.filter(internal=False, **kwargs)
.annotate(Sum('vote_set__vote'))
.order_by('-vote_set__vote__sum')
[:n])
objects = KbEntryManager()
class KbEntryQuestion(models.Model):
entry = models.ForeignKey(KbEntry, on_delete=models.CASCADE,
related_name='question_set')
language = models.CharField(max_length=2)
question = models.CharField(max_length=200)
class KbEntryAnswer(models.Model):
entry = models.ForeignKey(KbEntry, on_delete=models.CASCADE,
related_name='answer_set')
language = models.CharField(max_length=2)
answer = HTMLField()
class KbEntryVote(models.Model):
entry = models.ForeignKey(KbEntry, on_delete=models.CASCADE,
related_name='vote_set')
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL,
null=True)
create_date = models.DateTimeField(auto_now_add=True, editable=False)
vote = models.IntegerField()
def __str__(self):
return 'Vote %+d on %s by %s' % (self.vote, self.entry, self.user)
class Meta:
verbose_name = "Knowledgebase Entry Vote"

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

@ -0,0 +1,13 @@
from django.urls import path
from . import views
app_name = 'help'
urlpatterns = [
path('', views.kb_index, name='kb_index'),
path('<slug:category>/', views.kb_category, name='kb_category'),
path('<slug:category>/<int:entry>/', views.kb_entry, name='kb_entry'),
path('<slug:category>/<int:entry>/feedback/', views.kb_feedback, name='kb_feedback'),
]

@ -0,0 +1,42 @@
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.http import Http404
from django import forms
from django.forms import inlineformset_factory
from django.utils.translation import get_language
from .models import KbCategory, KbEntry
def kb_index(request):
return render(request, 'kb/kb_index.html', {
'categories': KbCategory.objects.all(),
})
def kb_category(request, category):
category = get_object_or_404(KbCategory, slug=category)
return render(request, 'kb/kb_category.html', {
'category': category,
'items': list(KbEntry.objects.filter(category=category)),
})
def kb_entry(request, category, entry):
entry = get_object_or_404(KbEntry, category__slug=category, pk=entry, internal=False)
return render(request, 'kb/kb_item.html', {
'item': entry,
})
@login_required
def kb_feedback(request, category, entry):
entry = get_object_or_404(KbEntry, category__slug=category, pk=entry, internal=False)
arg = request.GET.get('vote')
if arg == 'up':
entry.vote(request.user, 1)
elif arg == 'down':
entry.vote(request.user, -1)
return redirect(entry.get_absolute_url())

@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-09-07 21:02+0000\n"
"POT-Creation-Date: 2019-10-22 19:16+0000\n"
"PO-Revision-Date: 2016-04-07 01:32+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
@ -27,7 +27,7 @@ msgstr ""
msgid "hash"
msgstr ""
#: ccvpn/views.py:40 templates/tickets/layout.html:11
#: ccvpn/views.py:37
msgid "Live Chat"
msgstr "Chat Live"
@ -130,11 +130,11 @@ msgstr "Utilisateur de codes"
msgid "Gift Code Users"
msgstr "Utilisateurs de codes"
#: lambdainst/openvpn.py:10 templates/ccvpn/page.html:17
#: lambdainst/openvpn.py:10 templates/base_help.html:42
msgid "Windows"
msgstr "Windows"
#: lambdainst/openvpn.py:11 templates/ccvpn/page.html:16
#: lambdainst/openvpn.py:11 templates/base_help.html:38
msgid "Android"
msgstr "Android"
@ -142,7 +142,7 @@ msgstr "Android"
msgid "Ubuntu"
msgstr "Ubuntu"
#: lambdainst/openvpn.py:13 templates/ccvpn/page.html:19
#: lambdainst/openvpn.py:13 templates/base_help.html:50
msgid "OS X"
msgstr "OS X"
@ -150,7 +150,7 @@ msgstr "OS X"
msgid "iOS"
msgstr "iOS"
#: lambdainst/openvpn.py:15 templates/ccvpn/page.html:20
#: lambdainst/openvpn.py:15 templates/base_help.html:54
msgid "Chrome OS"
msgstr "Chrome OS"
@ -334,21 +334,15 @@ msgid "Confirming transaction"
msgstr "Confirmation de la transaction"
#: payments/backends/coinpayments.py:169
#, fuzzy
#| msgid "Payments"
msgid "CoinPayments"
msgstr "Paiements"
msgstr "CoinPayments"
#: payments/backends/coinpayments.py:198
#, fuzzy
#| msgid ""
#| "Waiting for PayPal to confirm the transaction... It can take up to a few "
#| "minutes..."
msgid ""
"Waiting for CoinPayments to confirm the transaction... It can take up to a "
"few minutes..."
msgstr ""
"En attente de la confirmation par Paypal... Cette étape peut durer quelques "
"En attente de la confirmation par CoinPayments... Cette étape peut durer quelques "
"minutes..."
#: payments/backends/paypal.py:14 payments/backends/paypal.py:15
@ -472,6 +466,43 @@ msgstr ""
msgid "Unknown content"
msgstr ""
#: templates/base_help.html:8
msgid "Help"
msgstr "Aide"
#: templates/base_help.html:13 templates/layout.html:55
msgid "Guides"
msgstr "Guides"
#: templates/base_help.html:19 templates/kb/kb_category.html:4
#: templates/kb/kb_index.html:4
msgid "Knowledge Base"
msgstr "F.A.Q."
#: templates/base_help.html:25
msgid "Self-Diagnosis"
msgstr "Auto-Diagnostic"
#: templates/base_help.html:30
msgid "Privacy"
msgstr "Vie Privée"
#: templates/base_help.html:34
msgid "Installation"
msgstr "Installation"
#: templates/base_help.html:46
msgid "GNU/Linux"
msgstr "GNU/Linux"
#: templates/base_help.html:58
msgid "Advanced"
msgstr "Avancé"
#: templates/base_help.html:62
msgid "Tor"
msgstr "Tor"
#: templates/ccvpn/chat.html:9
#, python-format
msgid ""
@ -593,26 +624,6 @@ msgstr ""
"<b>Profitez de l'IPv6</b> même sur les réseaux qui ne supportent pas ou mal "
"l'IPv6."
#: templates/ccvpn/page.html:8
msgid "Help"
msgstr "Aide"
#: templates/ccvpn/page.html:10
msgid "Frequently Asked Questions"
msgstr "Questions fréquemment posées"
#: templates/ccvpn/page.html:11
msgid "Self-Diagnosis"
msgstr "Auto-Diagnostic"
#: templates/ccvpn/page.html:14
msgid "Installation"
msgstr "Installation"
#: templates/ccvpn/page.html:18
msgid "GNU/Linux"
msgstr "GNU/Linux"
#: templates/ccvpn/require_email.html:8
msgid "E-mail Confirmation"
msgstr "Confirmation de l'adresse e-mail"
@ -664,6 +675,22 @@ msgstr "Mot de passe oublié ?"
msgid "Need help?"
msgstr "Besoin d'aide ?"
#: templates/kb/kb_index.html:7
msgid ""
"Please check to see if any of these answers address your problem prior to "
"opening a support ticket."
msgstr ""
"Veuillez vérifier si une des questions suivantes résolvent votre problème "
"avant d'ouvrir un ticket."
#: templates/kb/kb_index.html:20
msgid "View all questions"
msgstr "Voir toutes les questions"
#: templates/kb/kb_item.html:13
msgid "Did you find this answer useful?"
msgstr "Avez-vous trouvé cette réponse utile ?"
#: templates/lambdainst/account.html:23
#, python-format
msgid ""
@ -984,10 +1011,6 @@ msgstr "Se connecter"
msgid "VPN"
msgstr "VPN"
#: templates/layout.html:55
msgid "Guides"
msgstr "Guides"
#: templates/layout.html:57 templates/tickets/index.html:6
#: templates/tickets/layout.html:8 tickets/models.py:13
msgid "Support"
@ -1130,19 +1153,23 @@ msgstr "Sujet"
msgid "New Ticket"
msgstr "Nouveau ticket"
#: templates/tickets/layout.html:14
#: templates/tickets/layout.html:19
msgid "Open Tickets"
msgstr "Tickets ouverts"
#: templates/tickets/layout.html:16
#: templates/tickets/layout.html:26
msgid "Closed Tickets"
msgstr "Tickets fermés"
#: templates/tickets/layout.html:18
#: templates/tickets/layout.html:31
msgid "Staff"
msgstr ""
#: templates/tickets/layout.html:36
msgid "All Open"
msgstr "Tous ouverts"
#: templates/tickets/layout.html:20
#: templates/tickets/layout.html:43
msgid "All Closed"
msgstr "Tous fermés"
@ -1266,18 +1293,3 @@ msgstr "Peut envoyer des messages privés"
#: tickets/models.py:55
msgid "Waiting for staff"
msgstr "En attente du support"
#~ msgid ""
#~ "Error subscribing. It usually means you don't have enough money available."
#~ msgstr ""
#~ "Il y a une erreur à l'inscription. C'est le plus souvent un manque de "
#~ "fonds sur la carte."
#~ msgid "Subscribed!"
#~ msgstr "Abonné!"
#~ msgid "You can cancel it from PayPal account."
#~ msgstr "Vous pouvez annuler depuis votre compte PayPal."
#~ msgid "Do you really want to cancel your subscription?"
#~ msgstr "Voulez-vous vraimer annuler votre abonnement ?"

33
poetry.lock generated

@ -49,6 +49,14 @@ version = "2.2.1"
pytz = "*"
sqlparse = "*"
[[package]]
category = "main"
description = "Use dropdowns in Django admin list filter"
name = "django-admin-list-filter-dropdown"
optional = false
python-versions = "*"
version = "1.0.3"
[[package]]
category = "main"
description = "Django live settings with pluggable backends, including Redis."
@ -91,6 +99,18 @@ version = "2.0"
[package.dependencies]
Django = ">=1.11"
[[package]]
category = "main"
description = "A Django application that provides a fully functional TinyMCE 4 editor widget for models and forms."
name = "django-tinymce4-lite"
optional = false
python-versions = "*"
version = "1.7.5"
[package.dependencies]
Django = ">=1.8.0"
jsmin = "*"
[[package]]
category = "main"
description = "Internationalized Domain Names in Applications (IDNA)"
@ -107,6 +127,14 @@ optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "4.3.19"
[[package]]
category = "main"
description = "JavaScript minifier."
name = "jsmin"
optional = false
python-versions = "*"
version = "2.2.2"
[[package]]
category = "dev"
description = "A fast and thorough lazy object proxy."
@ -293,7 +321,7 @@ python-versions = "*"
version = "1.11.1"
[metadata]
content-hash = "5a877ca66b221fad6e7837be828b4474efe123d30feb664c6b11bb38edc4ce07"
content-hash = "c00450bd56aa5a669d833686086c1839e5f67dd1ed271fa7a1898d88d6a9ae10"
python-versions = "^3.5"
[metadata.hashes]
@ -302,12 +330,15 @@ certifi = ["59b7658e26ca9c7339e00f8f4636cdfe59d34fa37b9b04f6f9e9926b3cece1a5", "
chardet = ["84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", "fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"]
colorama = ["05eed71e2e327246ad6b38c540c4a3117230b19679b875190486ddd2d721422d", "f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48"]
django = ["6fcc3cbd55b16f9a01f37de8bcbe286e0ea22e87096557f1511051780338eaea", "bb407d0bb46395ca1241f829f5bd03f7e482f97f7d1936e26e98dacb201ed4ec"]
django-admin-list-filter-dropdown = ["07cd37b6a9be1b08f11d4a92957c69b67bc70b1f87a2a7d4ae886c93ea51eb53", "bf1b48bab9772dad79db71efef17e78782d4f2421444d5e49bb10e0da71cd6bb"]
django-constance = ["19ff1ae8295aeffc2917ab67da4b310bfaf8c42f34d570f89e289fd54c4217b0", "417f9866a4fcd93c198acd16d5bc22b68e491eaabb18efea4c70d183d42daa45"]
django-countries = ["5307a61172eee5740720e44ea08721858b7d8bf8509ec7701ccd7a8d21120b9a", "e4eaaec9bddb9365365109f833d1fd0ecc0cfee3348bf5441c0ccefb2d6917cd"]
django-jsonfield = ["af7938ebf0eb945d29648d80bad4845973f1ab1d9fea67f65a963753e913e271", "f357e196565daa503e914b6bdbeeaa104288a5e3b3f982a928a8de46f54e55ea"]
django-picklefield = ["9052f2dcf4882c683ce87b4356f29b4d014c0dad645b6906baf9f09571f52bc8", "f1733a8db1b6046c0d7d738e785f9875aa3c198215de11993463a9339aa4ea24"]
django-tinymce4-lite = ["e6776bc5b2c7237705fea18668574bc1c4dff36babc90c99a2bb7b5d636eb5e8", "f0958117ddacc72596e80746729e02a727264413ab54b799f3b697a44e054e87"]
idna = ["c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", "ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"]
isort = ["49293e2ff590cc8d48bc1f51970548b5b102bf038439ca1af77f352164725628", "ba69a4be8474be11720636bc2f0cf66f7054d417d4c1dbc1dfe504bb8e739541"]
jsmin = ["b6df99b2cd1c75d9d342e4335b535789b8da9107ec748212706ef7bbe5c2553b"]
lazy-object-proxy = ["159a745e61422217881c4de71f9eafd9d703b93af95618635849fe469a283661", "23f63c0821cc96a23332e45dfaa83266feff8adc72b9bcaef86c202af765244f", "3b11be575475db2e8a6e11215f5aa95b9ec14de658628776e10d96fa0b4dac13", "3f447aff8bc61ca8b42b73304f6a44fa0d915487de144652816f950a3f1ab821", "4ba73f6089cd9b9478bc0a4fa807b47dbdb8fad1d8f31a0f0a5dbf26a4527a71", "4f53eadd9932055eac465bd3ca1bd610e4d7141e1278012bd1f28646aebc1d0e", "64483bd7154580158ea90de5b8e5e6fc29a16a9b4db24f10193f0c1ae3f9d1ea", "6f72d42b0d04bfee2397aa1862262654b56922c20a9bb66bb76b6f0e5e4f9229", "7c7f1ec07b227bdc561299fa2328e85000f90179a2f44ea30579d38e037cb3d4", "7c8b1ba1e15c10b13cad4171cfa77f5bb5ec2580abc5a353907780805ebe158e", "8559b94b823f85342e10d3d9ca4ba5478168e1ac5658a8a2f18c991ba9c52c20", "a262c7dfb046f00e12a2bdd1bafaed2408114a89ac414b0af8755c696eb3fc16", "acce4e3267610c4fdb6632b3886fe3f2f7dd641158a843cf6b6a68e4ce81477b", "be089bb6b83fac7f29d357b2dc4cf2b8eb8d98fe9d9ff89f9ea6012970a853c7", "bfab710d859c779f273cc48fb86af38d6e9210f38287df0069a63e40b45a2f5c", "c10d29019927301d524a22ced72706380de7cfc50f767217485a912b4c8bd82a", "dd6e2b598849b3d7aee2295ac765a578879830fb8966f70be8cd472e6069932e", "e408f1eacc0a68fed0c08da45f31d0ebb38079f043328dce69ff133b95c29dc1"]
lcoreapi = []
markdown = ["fc4a6f69a656b8d858d7503bda633f4dd63c2d70cf80abdc6eafa64c4ae8c250", "fe463ff51e679377e3624984c829022e2cfb3be5518726b06f608a07a3aad680"]

@ -20,6 +20,8 @@ lcoreapi = {git = "https://git.packetimpact.net/lvpn/lcoreapi.git"}
pygments = "^2.3"
psycopg2-binary = "^2.8"
python-frontmatter = "^0.4.5"
django-tinymce4-lite = "^1.7"
django-admin-list-filter-dropdown = "^1.0"
[tool.poetry.dev-dependencies]
pylint = "^2.3"

@ -19,11 +19,10 @@ html, button, input, select, textarea,
}
a{
color: #1c619a;
color: #0b2d4f;
}
em {
color: #9A691C;
font-style: normal;
font-weight: bold;
}
@ -175,8 +174,8 @@ header nav a{
font-weight: 600;
}
.left-menu ul {
list-style-type: disc;
padding: 0.5em 1em 0.5em 30px;
list-style-type: none;
padding: 0.5em 1em 0.5em 1em;
margin: 0;
}
.left-menu li {
@ -186,7 +185,7 @@ header nav a{
text-decoration: none;
}
.left-menu + .content {
.left-menu + .content{
margin-left: 200px;
}
@ -217,6 +216,83 @@ header nav a{
padding-left: 2em;
}
.flex-page {
display: flex;
}
.flex-page .left-menu {
display: block;
float: none;
width: 200px;
position: relative;
margin-left: 1em;
flex-shrink: 0;
}
.content-box {
margin: 1em;
border: 1px solid #bbb;
padding: 2em 2em;
background: #fff;
overflow: auto;
flex-grow: 2;
-webkit-box-shadow: 1px 1px 2px 1px rgba(0,0,0,0.21);
-moz-box-shadow: 1px 1px 2px 1px rgba(0,0,0,0.21);
box-shadow: 1px 1px 2px 1px rgba(0,0,0,0.21);
}
.content-box h2 {
margin-top: 0;
font-size: 1.5em;
font-weight: bold;
color: #1c619a;
}
.content-box h3 {
font-weight: bold;
font-size: 1.2em;
margin: 0.5em 0 0.25em 0;
}
.content-box h4 {
font-weight: bold;
font-size: 1.0em;
margin: 1em 0 0.25em 2em;
}
.content-box ul {
margin: 0.25em 0 0.5em 0;
}
.content-box ul {
list-style-type: circle;
}
.content-box hr {
height: 0;
border: 0;
border-top: 1px solid #ccc;
padding: 0;
margin: 1.5em 0;
}
/*.kb-question-list {
list-style-type: circle;
}
.kb-question-list a {
font-size: 1.2em;
}*/
.kb-question-meta {
}
.kb-question-meta .kb-vote-buttons {
padding-left: 0.5em;
}
.kb-vote-buttons button {
padding: 0 0.4em 0.2em 0.4em;
border: 1px solid #ccc;
border-radius: 3px;
}
.kb-question-meta p {
margin: 0 0;
}
footer{
padding-top: 4em;

@ -0,0 +1,73 @@
{% extends 'layout.html' %}
{% load i18n %}
{% load staticfiles %}
{% block content %}
<div class="flex-page">
<div class="left-menu">
<p class="menu-title">{% trans 'Help' %}</p>
<ul>
<li class="pure-menu-item">
<a href="{% url 'page' 'help' %}">
<i class="fa fa-life-ring fa-fw" aria-hidden="true"></i>&nbsp;
{% trans 'Guides' %}
</a>
</li>
<li class="pure-menu-item">
<a href="{% url 'kb:kb_index' %}">
<i class="fa fa-book fa-fw" aria-hidden="true"></i>&nbsp;
{% trans 'Knowledge Base' %}
</a>
</li>
<li class="pure-menu-item">
<a href="/page/self-diagnosis">
<i class="fa fa-wrench fa-fw" aria-hidden="true"></i>&nbsp;
{% trans 'Self-Diagnosis' %}
</a>
</li>
<li><a href="/page/privacy">
<i class="fa fa-shield fa-fw" aria-hidden="true"></i>&nbsp;
{% trans 'Privacy' %}
</a></li>
</ul>
<p class="menu-title">{% trans 'Installation' %}</p>
<ul>
<li><a href="/page/install-android">
<i class="fa fa-android fa-fw" aria-hidden="true"></i>&nbsp;
{% trans 'Android' %}
</a></li>
<li><a href="/page/install-windows">
<i class="fa fa-windows fa-fw" aria-hidden="true"></i>&nbsp;
{% trans 'Windows' %}
</a></li>
<li><a href="/page/install-gnulinux">
<i class="fa fa-linux fa-fw" aria-hidden="true"></i>&nbsp;
{% trans 'GNU/Linux' %}
</a></li>
<li><a href="/page/install-osx">
<i class="fa fa-apple fa-fw" aria-hidden="true"></i>&nbsp;
{% trans 'OS X' %}
</a></li>
<li><a href="/page/install-chromeos">
<i class="fa fa-chrome fa-fw" aria-hidden="true"></i>&nbsp;
{% trans 'Chrome OS' %}
</a></li>
</ul>
<p class="menu-title">{% trans 'Advanced' %}</p>
<ul>
<li><a href="/page/advanced-tor">
<i class="fa fa-user-secret fa-fw" aria-hidden="true"></i>&nbsp;
{% trans 'Tor' %}
</a></li>
</ul>
</div>
<div class="content-box">
{% if title %}
<h2>{{ title }}</h2>
{% endif %}
{% block helpdesk_body %}{% endblock %}
</div>
</div>
{% endblock %}

@ -1,36 +1,7 @@
{% extends 'layout.html' %}
{% extends 'base_help.html' %}
{% load i18n %}
{% load staticfiles %}
{% block content %}
<div class="page">
<div class="left-menu">
<p class="menu-title">{% trans 'Help' %}</p>
<ul>
<li><a href="/page/faq">{% trans 'Frequently Asked Questions' %}</a></li>
<li><a href="/page/self-diagnosis">{% trans 'Self-Diagnosis' %}</a></li>
</ul>
<p class="menu-title">{% trans 'Installation' %}</p>
<ul>
<li><a href="/page/install-android">{% trans 'Android' %}</a></li>
<li><a href="/page/install-windows">{% trans 'Windows' %}</a></li>
<li><a href="/page/install-gnulinux">{% trans 'GNU/Linux' %}</a></li>
<li><a href="/page/install-osx">{% trans 'OS X' %}</a></li>
<li><a href="/page/install-chromeos">{% trans 'Chrome OS' %}</a></li>
</ul>
<p class="menu-title">{% trans 'Advanced' %}</p>
<ul>
<li><a href="/page/advanced-tor">{% trans 'Tor' %}</a></li>
</ul>
</div>
<div class="content">
{% if title %}
<h1>{{ title }}</h1>
{% endif %}
{% block helpdesk_body %}
{{ content|safe }}
</div>
</section>
{% endblock %}
{% endblock %}

@ -0,0 +1,19 @@
{% extends "base_help.html" %}{% load i18n %}{% load i18n humanize %}
{% block helpdesk_body %}
<h2>{% trans 'Knowledge Base' %}: {{ category.name }}</h2>
<div class="block padded-block">
<h3>{{ category.name }}</h3>
{% if category.description %}
<p>{{ category.description }}</p>
{% endif %}
<ul class="kb-question-list">
{% for item in items %}
<li><a href="{{ item.get_absolute_url }}">{{ item.question }}</a></li>
{% endfor %}
</ul>
</div>
{% endblock %}

@ -0,0 +1,28 @@
{% extends "base_help.html" %}{% load i18n %}
{% block helpdesk_body %}
<h2>{% trans "Knowledge Base" %}</h2>
<div class="block padded-block">
<p>{% trans "Please check to see if any of these answers address your problem prior to opening a support ticket." %}</p>
{% for category in categories %}
{% with category.get_entry_count as entry_count %}
{% if entry_count >= 1 %}
<h3>{{ category.name }}</h3>
<ul class="kb-cat-top-questions">
{% for item in category.get_top_entries %}
<li><a href="{{ item.get_absolute_url }}">{{ item.question }}</a></li>
{% endfor %}
{% if entry_count > config.KB_MAX_TOP_ENTRIES %}
<li class="more">
<a href='{{ category.get_absolute_url }}'><b>{% trans 'View all questions' %}</b></a>
</li>
{% endif %}
</ul>
{% endif %}
{% endwith %}
{% endfor %}
</div>
{% endblock %}

@ -0,0 +1,24 @@
{% extends "base_help.html" %}{% load i18n humanize %}
{% block helpdesk_body %}
<h2>{{ item.question }}</h2>
{{ item.answer|safe }}
{% if request.user.is_authenticated %}
<hr />
<div class="block block-note kb-question-meta">
<p>
{% trans "Did you find this answer useful?" %}
<span class="kb-vote-buttons">
<a href='feedback/?vote=up'><button type="button"><i class="fa fa-thumbs-up fa-lg"></i></button></a>
<a href='feedback/?vote=down'><button type="button"><i class="fa fa-thumbs-down fa-lg"></i></button></a>
</span>
({{ item.get_score }} with {{ item.get_vote_count }} votes)
</p>
</div>
{% endif %}
{% endblock %}

@ -14,7 +14,7 @@ This page will go over the methods and their uses and issues.
[TOC]
## a. Tor through the VPN
### a. Tor through the VPN
Much better for anonymity, but requires careful use of end-to-end encryption (HTTPS, SSH, ...)
@ -32,9 +32,10 @@ Much better for anonymity, but requires careful use of end-to-end encryption (HT
1. Install the VPN.
2. Install tor or the Tor Browser Bundle.
3. By using the Tor SOCKS proxy or the Tor Browser, you will effectively be using Tor over the VPN.
## b. VPN through Tor
### b. VPN through Tor
Harder to keep anonymous but will provide a clean and secure connection even over Tor.
@ -46,24 +47,28 @@ Harder to keep anonymous but will provide a clean and secure connection even ove
#### Cons:
- this anonymity is lessed depending on the payment method used for the VPN.
- your anonimity depends on the payment method used for the VPN.
- the bandwidth will be limited by Tor and its network.
- VPN servers aren't as anonymous as most Tor exit nodes. please don't get us into any trouble.
#### Installation:
1. Install Tor. The exact method will be highly OS/distribution specific.
2. Set up the VPN to use Tor:
Edit your VPN configuration file to append the following config (or add it in the "additional config" in CCVPNGUI):
socks-proxy-retry
socks-proxy 127.0.0.1 9050
Replace 9050 by 9150 when using the Tor Browser Bundle.
3. (Re)connect to the VPN to start using it through Tor.
**Do not** use the Tor Browser Bundle or SOCKS proxy directly if you want to go through the VPN too.
1. We will assume using a separate host or virtual machine for Tor.
This configuration is implemented by Whonix and Qubes, and we recommend it for strong
anonymity. It also greatly simplifies routing and avoids some simple failure modes.
2. Set up the VPN on the "Workstation" (your host or VM behind the Tor gateway)
* You will need a TCP configuration to go over Tor
* Whonix Workstation: you will need to loosen the local firewall to be able to use a VPN:
`sudo iptables -I OUTPUT -j ACCEPT`
It shouldn't have serious security implications, providing that your physical network (or virtual network between VM)
is properly isolated.
* Whonix Workstation: change the default DNS server to use the VPN's server:
`echo "nameserver 10.99.0.20" | sudo tee /etc/resolv.conf`
* Whonix Workstation: using the default browser will always use Tor through a proxy.
The easiest workaround is to install and use a regular version of Firefox:
`sudo apt install firefox-esr`
3. Your trafic should be sent to the VPN, over Tor.
Your current IP address as seen from a website visited on your workstation VM should be linked to the VPN.

@ -1,139 +0,0 @@
---
Title: Frequently Asked Questions
---
[TOC]
General
-------
### What is a VPN? How does it work?
A Virtual Private Network is a virtual network that provides a secure
and reliable connection between two points over the Internet.
Our VPN forwards your traffic through our VPN servers to prevent it
from being analyzed, filtered, or modified between you and the server
and hides its original source.
Instead of seeing your own IP address and finding your ISP and approximate
geolocation, websites will only see the IP address of the VPN server.
It lets you pick the country and blend in as anyone behind the VPN server.
### How does it compare to tor?
Tor, although free and decentralized, is not designed for the same usage.
It provides better anonymity than a VPN, at the cost of much reduced performances
and in some cases security.
While communications are very secure between two tor nodes,
to communicate to the existing web ("clearnet") it needs *exit nodes*
that will see and handle all your traffic, and some of those have been
seen to abuse that trust. Our servers don't do that.
A VPN can be used for everyday browsing, online gaming, and you can
pick a server close to you for best performances.
For anonymity, tor can be used over the VPN to hide your tor usage to
your ISP or school, as it could be used against you.
### Do you propose an affiliate program?
Yes, sare your affiliate link and earn 2 weeks for each referral that pays.
Invite 24 people and you get one year of free VPN!
### Is P2P allowed?
On some servers. You can see it in CCVPNGUI and on the configuration download page.
### Can I have a dedicated IP address?
Not at the moment.
### Do you limit bandwidth usage?
Every user of a server share its connection without hard limit.
We try to always have enough bandwidth (at least 20Mbps) available
for each connection.
### Do you censor some websites or protocols?
No. BitTorrent is forbidden on some servers.
### Which protocols are supported?
We only support OpenVPN for now.
### Which payment methods are supported?
We support Paypal, credit cards (via Stripe) and many cryptocurrencies (BTC, XMR, LTC, ETH, ...).
Feel free to ask [the support](/page/help) if you need any other method.
### Is it free software?
Yes! Our VPN is based on OpenVPN and we try to release most of our own work as free software.
* [Our Windows OpenVPN GUI](https://github.com/PacketImpact/lvpngui/)
* [This website](https://github.com/CCrypto/ccvpn3/)
### Are my data kept secure?
Yes, the VPN traffic is strongly encrypted and we do not keep any data on the
VPN servers.
The website and database are on a different server, in a
different datacenter.
### Will there be more servers/countries available?
Yes, but we first need money to pay the servers.
If you would like to have a server somewhere, know a good provider or would
like to host one, please contact us.
Account
-------
### Can I have a trial account?
Yes, you just have to [sign up](/account/signup) and click on the dedicated button
to get a repeatable free 2-hour test period. The limit is a full week.
### Can I use my account on multiple machines?
Yes, you can! Up to 10 at the same time!
### How can I delete my account?
Contact [the support](/page/help).
Technical
---------
### Encryption used
Authentication uses a 4096 bits RSA key. (3072 bits on oldest servers)
The current recommended key size considered safe until 2030 is 2048 bits.
VPN trafic encryption is performed with the best cipher available to OpenVPN
(with a recent version AES 256 GCM)
using a random 256 bits key re-generated regularly, and unique to a VPN connection.
Key Exchange uses a 3072 bits Diffie-Hellman parameters.
A 2048 bits key is considered safe until 2030.
### Do you support IPv6?
Yes, most of our servers are dual stack - they perfectly support IPv4 and IPv6
at the same time.
Some are IPv4 only (but we're working with our providers to fix it) and will
block all IPv6 traffic to make sure your IPv6 address is not leaked.
### Do you support PPTP?
No, PPTP is not supported and will not be supported.
PPTP is considered insecure and should never be used.
Legal
-----
### What do you log?
See our [privacy policy](/page/privacy) page.
Your traffic through the VPN is never logged, but VPN connections are.
### Is it really anonymous?
We will not ask your name and you can pay with bitcoins.
The VPN will hide your identity from people over the Internet,
and can help you achieve anonymity by not leaking information through your IP address.
It will however not make you untraceable.
### Will you log traffic or send user data to authorities?
We won't log your traffic under any condition.
We may give the little we know about you to authorities
only if required by the law to keep the service running.
In this case, we'll try to contact you before doing anything if possible.

@ -1,148 +0,0 @@
---
Title: Questions fréquemment posées
---
[TOC]
Géneral
-------
### Qu'est-ce qu'un VPN ? Comment ça marche ?
Un VPN (Réseau Privé Virtuel) est un réseau virtual permettant
d'établir une connexion sécurisée entre deux points d'Internet.
Notre VPN redirige votre traffic vers nos serveurs VPN à travers le tunnel
sécurisé, le protégeant contre la lecture et l'interception par un tiers,
et cachant son origine.
Au lieu de voir votre adresse IP and d'en déduire une localisation approximative,
les sites web ne verront que l'adresse du VPN.
Cela vous donne le choix du pays depuis lequel apparaitre, et vous permet
de vous fondre dans la masse des utilisateurs de ce serveur.
### Quelles sont les différences avec tor ?
Tor, bien que gratuit et décentralisé, n'est pas fait pour le même usage.
Il fournit un meilleur anonymat qu'un VPN, mais au coût de performances
très réduits et dans certains cas la sécurité.
La communication entre deux noeuds tor est bien sécurisée, mais pour accéder
au reste du web ("clearnet") le réseau tor passe par des *exit nodes*
qui vont avoir accès à votre traffic, et certains ont déjà été vu abuser de
cette position. Nos serveurs ne font pas ça.
Un VPN peut être utilisé pour la navigation de tous les jours,
les jeux en ligne, et vous pouvez choisir un serveur proche de vous
pour les meilleures performances.
Pour l'anonymat, tor peut être utilisé en plus du VPN, pour cacher votre
utilisation de tor à votre FAI ou école qui pourrait utiliser ça contre vous.
### Avez-vous un programme d'affiliation ?
Oui, vous pouvez partager un lien associé à votre compte, qui vous
fera gagner 2 semaines de VPN pour chaque client l'ayant suivi.
Inviter 24 personnes vous donne donc 1 an de VPN gratuit !
### Est-ce que le P2P est autorisé ?
Sur certains serveurs. C'est indiqué dans CCVPNGUI et sur la page
de téléchargement de config.
### Puis-je avoir une adresse dédiée ?
Non, pas pour le moment.
### Y a-t-il une limite de bande passante ?
Non, tous les utilisateurs partagent équitablement la connexion des serveurs.
Nous faisons en sorte qu'il y ait toujours un minimum de 20Mbps disponible
pour chaque client.
### Censurez-vous certains sites ou protocoles ?
Non. Le BitTorrent est interdit sur certains serveurs.
### Avec quels protocoles fonctionne le VPN ?
Notre VPN est fait avec OpenVPN.
### Quelles méthodes de payement sont disponibles ?
Vous pouvez payer par Paypal, carte (via Stripe), et plusieurs cryptomonnaies.
Vous pouvez [nous contacter](/page/help) si vous avez besoin d'un autre moyen
de payement.
### Est-ce Libre ?
Oui ! Notre VPN fonctionne avec OpenVPN, et nous essayons de distribuer
une grande partie de notre travail comme logiciel libre.
* [Notre logiciel client pour Windows](https://github.com/PacketImpact/lvpngui/)
* [Ce site](https://github.com/CCrypto/ccvpn3/)
### Est-ce vraiment sécurisé ?
Oui, le VPN utilise différents algorithmes de chiffrement fiables et nous ne
gardons aucune données sensible sur les serveurs du VPN.
Les comptes clients et historiques de connexions sont uniquement gardés sur des
serveurs séparés.
### Y aura-t-il plus de serveurs ou dans d'autres pays ?
Oui, nous ajoutons des serveurs en fonction de la demande et de nos moyens.
Si vous voudriez héberger un serveur, recommander un bon hébergeur, ou
seriez simplement intéressé par une certain pays, contactez nous.
Comptes
-------
### Puis-je avoir un compte de test gratuit ?
Oui, vous n'avez qu'à [créer un compte](/account/signup) et cliquer sur
le bouton dédié pour recevoir une période d'essai gratuite de 2h répétable.
La limite est d'une semaine entière.
### Puis-je utiliser mon compte sur plusieurs machines ?
Oui, vous pouvez utiliser votre compte avec un maximum de 10 connexions
simultannées.
### Comment supprimer mon compte ?
[Contactez nous](/page/help).
Technique
---------
### Chiffrement
L'authentification utilise une clé RSA de 4096 bits. (3072 sur les serveurs plus anciens)
Les clés de 2048 bits ou plus sont considérées sûres jusqu'à 2030.
Le traffic est chiffré avec le meilleur algorithme disponible pour OpenVPN
(AES 256 GCM dans les versions récentes),
en utilisant une clé aléatoire de 256 bits re-générée régulièrement
et unique pour chaque connexion au VPN.
L'échange de clés (Diffie-Hellman) utilise un groupe de 3072 bits.
2048 bits ou plus est considéré suffisant jusqu'en 2030.
### Est-ce que l'IPv6 est supporté ?
Oui, la plupart des serveurs fonctionnent en IPv4 et IPv6 (dual stack).
Quelques-uns ne fonctionnent qu'en IPv4 et bloquent entièrement l'IPv6 pour
éviter de laisser passer votre addresse IPv6.
### Est-ce que le PPTP est supporté ?
Non, le PPTP n'est plus considéré sécurisé et ne doit plus être utilisé.
Légal
-----
### Quelles informations gardez-vous ?
Voyez notre [politique de confidentialité](/page/privacy).
Nous n'enregistrons jamais votre traffic dans le VPN,
mais les connexions au VPN sont loggées.
### Est-ce réellement anonyme ?
Nous ne vous demanderons pas votre nom et nous acceptons les paiements anonymes.
Le VPN cachera votre identité lors de communications sur Internet,
et peut vous aider à atteindre un niveau d'anonymat en évitant de laisser
filtrer informations par l'adresse IP.
Cela ne vous rendra pas pour autant intraçable et ne permet pas d'achapper à la loi.
### Donnez vous des informations aux autorités ?
Nous ne vous espionnerons jamais.
Le peu de données enregistrées peuvent être transmises aux autorités si requis
par la loi.
Dans ce cas, nous essaierons de contacter les clients concernés avant tout,
si possible.

@ -3,7 +3,7 @@ Title: Guides
---
## Installation
### Installation
<ul class="install-guides">
<li><a href="/page/install-android"><i class="fa fa-android fa-5x"></i> Android</a></li>
@ -13,9 +13,10 @@ Title: Guides
<li><a href="/page/install-chromeos"><i class="fa fa-chrome fa-5x"></i> Chromebook</a></li>
</ul>
## Support
### Support
- [**Frequently Asked Questions**](/page/faq)
- [**Privacy**](/page/privacy)
- **[Self-Diagnosis](/page/self-diagnosis)**: Before asking for help, check here if you find the solution to your problem.
- [**Knowledge Base**](/kb/)
- [**Self-Diagnosis**](/page/self-diagnosis): Before asking for help, check here if you find the solution to your problem.
- [**Tickets**](/tickets/)
- E-mail: **support at ccrypto.org**

@ -2,7 +2,7 @@
Title: Guides
---
## Installation
### Installation
<ul class="install-guides">
<li><a href="/page/install-android"><i class="fa fa-android fa-5x"></i> Android</a></li>
@ -12,9 +12,9 @@ Title: Guides
<li><a href="/page/install-chromeos"><i class="fa fa-chrome fa-5x"></i> Chromebook</a></li>
</ul>
## Support
### Support
- [**Questions fréquemment posées**](/page/faq)
- [**Informations personnelles et vie privée**](/page/privacy)
- [**F.A.Q.**](/kb/)
- [**Auto-Diagnostic**](/page/self-diagnosis) : Avant de demander de l'aide, vérifiez si vous trouvez la solution à votre problème ici.
- [**Tickets**](/tickets/)
- E-mail: **support at ccrypto.org**

@ -2,8 +2,7 @@
Title: Install on GNU/Linux
---
With NetworkManager
-------------------
### With NetworkManager
1. Download and install OpenVPN and the NetworkManager plugin with your package manager.
@ -35,8 +34,7 @@ With NetworkManager
3. Save the new connection and connect to it.
With systemd (Arch, Fedora 16 or later, Debian 8 or later, ...)
------------
### With systemd (Arch, Fedora 16 or later, Debian 8 or later, ...)
1. Download and install OpenVPN with your package manager.

@ -2,8 +2,7 @@
Title: Installation sous GNU/Linux
---
Avec NetworkManager
-------------------
### Avec NetworkManager
1. Téléchargez et installez OpenVPN et le plugin NM avec votre gestionnaire de paquets :
@ -35,8 +34,7 @@ Avec NetworkManager
3. Enregistrez la connexion et connectez-vous.
Avec systemd (Arch, Fedora 16 ou plus, Debian 8 ou plus, ...)
------------
### Avec systemd (Arch, Fedora 16 ou plus, Debian 8 ou plus, ...)
1. Téléchargez et installez OpenVPN avec votre gestionnaire de paquets :

@ -3,8 +3,7 @@ Title: Install on Windows
---
{% load dltags %}
With CCVPN GUI (recommended, simple)
-------------
### With CCVPN GUI (recommended, simple)
CCVPN GUI is made for CCrypto VPN and contains everything it needs.
{% download_button "ccvpngui" "windows" %}
@ -19,8 +18,7 @@ It's open-source and based on [LVPNGUI](https://github.com/PacketImpact/lvpngui/
---
With OpenVPN GUI (advanced)
----------------
### With OpenVPN GUI (advanced)
1. Download OpenVPN for Windows on
[OpenVPN.net](http://openvpn.net/index.php/open-source/downloads.html)

@ -3,8 +3,7 @@ Title: Installation sous Windows
---
{% load dltags %}
Avec CCVPN GUI (recommandé, simple)
-------------
### Avec CCVPN GUI (recommandé, simple)
CCVPN GUI est fait pour CCrypto VPN et contient tout ce qu'il faut.
{% download_button "ccvpngui" "windows" %}
@ -19,8 +18,7 @@ C'est open-source et basé sur [LVPNGUI](https://github.com/PacketImpact/lvpngui
---
Avec OpenVPN GUI (avancé)
----------------
### Avec OpenVPN GUI (avancé)
1. Téléchargez le Windows Installer d'OpenVPN sur
[OpenVPN.net](http://openvpn.net/index.php/open-source/downloads.html)

@ -8,7 +8,7 @@ in what conditions, and the exact limits under which it is kept and transfered.
If you have any question that is not answered by this page, please contact us.
## 1. Informations stored
### 1. Informations stored
To run our VPN service, we collect and store the following informations:
@ -24,16 +24,16 @@ For each payment or subscription, we store:
- Stripe: the Stripe charge or subscription ID and paid amount
- Bitcoin: the transaction id, receiving address and received amount at the time the payment was confirmed.
We also use Piwik to monitor visitors on our website; it may record anonymized IP addresses,
pages viewed, referrer, and some informations about your browser.
All these informations are strictly kept by CCrypto and will not be shared to a third party,
except as described in sections 2 and 4.
except as described in section 4.
Our websites embeds a support chat widget operated by Tawk.to. It can be blocked
without breaking the rest of the website and tickets can be used for communication.
We use no external analytics or advertisement network on our website.
We use no additional external analytics or advertisement network on our website.
## 2. VPN Logging
### 2. VPN Logging
Each connection from a VPN client to our VPN server is logged for security and billing purposes.
For each connection or authentication, we store for up to a year:
@ -46,25 +46,16 @@ For each connection or authentication, we store for up to a year:
As opposed to many VPN service providers, no data is stored or logged in the gateway servers.
Those are too exposed and would be the easiest target to raid or steal, and depend on the
law of many countries.
Instead, connection logs are stored separately on a secure server.
Instead, logs are stored separately on a secure server operated by LambdaVPN in France,
who is also managing the gateway servers.
LambdaVPN has no access to any other user information
and has agreed not to share or use any information they store except on request by CCrypto.
In case of abuse or data request from any authority, LambdaVPN does not
have access to any payment information or email address directly and can
only forward the request to CCrypto.
These conditions are stated in the contract between CCrypto and LambdaVPN.
**CCrypto or LambdaVPN will never, in any event, monitor, record, or use without your consent the traffic you send and receive through the VPN, including but not limited to DNS queries and browsing history.**
**CCrypto will never, in any event, monitor, record, or use without your consent the traffic you send and receive through the VPN, including but not limited to DNS queries and browsing history.**
On some servers, we will however watch for known dangerous patterns to limit abuse,
as explicitly described by a dedicated page: [NO-P2P](/page/nop2p)
as explicitly described by a dedicated page: [NO-P2P](/page/nop2p)
Such detections are exclusively for use by CCrypto internally and will not be shared.
## 3. DMCA handling
### 3. DMCA handling
DMCA cease & desists are usually ignored as we have very little control over it.
If one user generates too many abuse, we may investigate and block their access
@ -81,7 +72,7 @@ Please do not abuse the service, as it will only lower the quality for everyone.
**We will never disclose user information as a result of a DMCA notice.**
## 4. Data requests
### 4. Data requests
The French government may request informations about VPN connections and payments as required by the French law.
We will only comply to this kind of request if they are following the right legal procedure.

@ -3,13 +3,12 @@ Title: Self Diagnosis
---
Windows
-------
### Windows
*Before anything, make sure you have started OpenVPN as Administrator and that your
config files exist in `C:\Program Files\OpenVPN\config\`.*
Before anything, make sure you have started OpenVPN as Administrator and that your
config files exist in `C:\Program Files\OpenVPN\config\`.
### netsh.exe error
#### netsh.exe error
If you find lines like those in your OpenVPN log:
@ -24,7 +23,7 @@ for example "Local Area Network" to "lan".
- [Rename a network connection](http://windows.microsoft.com/en-au/windows-vista/rename-a-network-connection)
### Multiple TAP-Windows adapters
#### Multiple TAP-Windows adapters
Error: When using --tun-ipv6, if you have more than one TAP-Windows adapter, you must also specify --dev-node
Exiting due to fatal error
@ -46,34 +45,33 @@ new line:
Replace [name] by your TAP adapter name.
### Still doesn't work
#### Still doesn't work
If you still cannot use the VPN, please go to the [Support page](/page/help)
and we'll do our best to help you.
Please also send us your OpenVPN logs.
GNU/Linux
---------
### GNU/Linux
### I have a ".ovpn" file but I need a ".conf"!
#### I have a ".ovpn" file but I need a ".conf"!
You just have to change the extension by renamming the file.
.conf is more commonly used on GNU/Linux, but it's the same as the .ovpn file.
### I'm unable to use your VPN with Network-Manager.
#### I'm unable to use your VPN with Network-Manager.
First, check that you have properly created the profile (tutorial to come).
If it's the case, before anything else, let's make sure that OpenVPN itself is working with the following command:
`sudo openvpn --config ccrypto.conf`
(make sure to replace "ccrypto.conf" by the actual name of your configuration file)
### I'm connected but cannot ping google.com
#### I'm connected but cannot ping google.com
Try to `ping 8.8.8.8`: if it works then your computer doesn't use the right DNS server.
Add `nameserver 10.99.0.20` at the beginning of /etc/resolv.conf **once the connection is made**.
Else, continue reading.
### It still doesn't work!
#### It still doesn't work!
Using the `ip route` command, make sure you have, alongside with other lines, the following:
0.0.0.0/1 via 10.99.2.1 dev tun0
@ -88,6 +86,6 @@ If you don't know how to do it, it would be best to come ask on IRC (we will nee
please paste them into https://paste.cubox.me and just give us the link to the paste).
### I've tried everything but nothing seems to work! T_T
#### I've tried everything but nothing seems to work! T_T
Ok… I guess now you can come [ask us on IRC](/chat) (but remember to stay a while, we're not payed professionnal, we might not be around at a given time but we will answer later on).

@ -3,14 +3,13 @@ Title: Auto-Diagnostic
---
Windows
-------
### Windows
*Tout d'abord, assurez vous d'avoir bien démarré OpenVPN en tant qu'administrateur
Tout d'abord, assurez vous d'avoir bien démarré OpenVPN en tant qu'administrateur
et que votre fichier de configuration est correctement placé dans
`C:\Program Files\OpenVPN\config\`.*
`C:\Program Files\OpenVPN\config\`.
### netsh.exe
#### netsh.exe
Si vous trouvez ces lignes dans votre historique OpenVPN:
@ -25,7 +24,7 @@ Par exemple « Connexion au réseau local » en « lan ».
- [(fr) Renommer une connexion réseau](http://windows.microsoft.com/fr-xf/windows-vista/rename-a-network-connection)
### Multiples interfaces TAP
#### Multiples interfaces TAP
Error: When using --tun-ipv6, if you have more than one TAP-Windows adapter, you must also specify --dev-node
Exiting due to fatal error
@ -46,7 +45,7 @@ et ajoutez ceci sur une nouvelle ligne :
Remplacez [nom] par le nom de votre interface TAP.
### Ça ne fonctionne toujours pas ?
#### Ça ne fonctionne toujours pas ?
Si vous ne pouvez toujours pas utiliser le VPN, n'hésitez pas à
[nous contacter](/page/help).
@ -54,22 +53,21 @@ Joignez les logs d'OpenVPN à votre message, pour nous aider à trouver
le problème au plus vite.
GNU/Linux
---------
### GNU/Linux
### J'ai un fichier ".ovpn" mais il me faut un ".conf" !
#### J'ai un fichier ".ovpn" mais il me faut un ".conf" !
Il vous suffit de changer l'extension en renommant le fichier.
### Il m'est impossible d'utiliser votre VPN avec Network-Manager.
#### Il m'est impossible d'utiliser votre VPN avec Network-Manager.
Tout d'abord, vérifiez que vous avez correctement créé le profil (tutoriel à venir).
Si c'est bien le cas, avant toute chose, vérifiez qu'OpenVPN lui-même est opérationnel en utilisant cette commande :
`sudo openvpn --config ccrypto.conf`
(assurez-vous de remplacer "ccrypto.conf" par le nom de votre fichier de configuration)
### Je suis connecté mais je ne peux pas ping google.com
#### Je suis connecté mais je ne peux pas ping google.com
Essayez de `ping 8.8.8.8`, si ça marche, votre ordinateur n'utilise pas le serveur DNS. Ajoutez `nameserver 10.99.0.20` au début de /etc/resolv.con **une fois la connexion établie**. Sinon, lisez la suite.
### Ça ne marche toujours pas !
#### Ça ne marche toujours pas !
En utilisant la commande `ip route`, vérifiez que vous avez, entre autre choses, les lignes suivantes :
0.0.0.0/1 via 10.99.2.1 dev tun0
@ -84,6 +82,6 @@ Si vous ne savez pas comment faire, ce serait mieux de venir nous demander sur I
(nous allons avoir besoin des sorties des commandes `ip addr` et `ip route`,
veuillez utiliser https://paste.cubox.me et nous envoyer uniquement le lien vers le paste).
### J'ai tout essayé mais rien ne semble fonctionner ! T_T
#### J'ai tout essayé mais rien ne semble fonctionner ! T_T
Ok… Je pense que vous pouvez venir [nous demander sur IRC](/chat) (mais souvenez-vous que nous ne sommes pas des professionnels payés, nous ne sommes pas toujours présent mais nous finirons toujours par répondre si vous ne partez pas trop vite).

@ -3,25 +3,50 @@
{% load staticfiles %}
{% block content %}
<div class="page">
<div class="flex-page">
<div class="left-menu">
<p class="menu-title">{% trans 'Support' %}</p>
<ul>
{% if not SUPPORT_HTML %}
<li><a href="/chat"><b>{% trans 'Live Chat' %}</b></a></li>
{% endif %}
<li><a href="/tickets/new"><b>{% trans 'New Ticket' %}</b></a></li>
<li><a href="/tickets/open">{% trans 'Open Tickets' %}
{% if open_n > 0 %}({{open_n}}){% endif %}</a></li>
<li><a href="/tickets/closed">{% trans 'Closed Tickets' %}</a></li>
{% if perms.tickets.view_any_ticket %}
<li><a href="/tickets/all_open">{% trans 'All Open' %}
{% if all_open_n > 0 %}({{all_open_n}}){% endif %}</a></li>
<li><a href="/tickets/all_closed">{% trans 'All Closed' %}</a></li>
{% endif %}
<li class="pure-menu-item">
<a href="{% url 'tickets:new' %}">
<i class="fa fa-plus-square fa-fw" aria-hidden="true"></i>&nbsp;
{% trans 'New Ticket' %}
</a>
</li>
<li class="pure-menu-item">
<a href="/tickets/open">
<i class="fa fa-folder-open fa-fw" aria-hidden="true"></i>&nbsp;
{% trans 'Open Tickets' %}
{% if open_n > 0 %}({{open_n}}){% endif %}
</a>
</li>
<li class="pure-menu-item">
<a href="/tickets/closed">
<i class="fa fa-folder fa-fw" aria-hidden="true"></i>&nbsp;
{% trans 'Closed Tickets' %}
</a>
</li>
</ul>
{% if perms.tickets.view_any_ticket %}
<p class="menu-title">{% trans 'Staff' %}</p>
<ul>
<li class="pure-menu-item">
<a href="/tickets/all_open">
<i class="fa fa-fire-extinguisher fa-fw" aria-hidden="true"></i>&nbsp;
{% trans 'All Open' %}
{% if all_open_n > 0 %}({{all_open_n}}){% endif %}
</a>
</li>
<li class="pure-menu-item">
<a href="/tickets/all_closed">
<i class="fa fa-archive fa-fw" aria-hidden="true"></i>&nbsp;
{% trans 'All Closed' %}
</a>
</li>
</ul>
{% endif %}
</div>
<div class="content">
<div class="content-box">
{% block tickets_content %}{% endblock %}
</div>
</div>

@ -3,7 +3,7 @@
{% load staticfiles %}
{% block tickets_content %}
<h1>{% trans 'Tickets' %}</h1>
<h2>{% trans 'Tickets' %}</h2>
{% if tickets %}
<table class="admin-list">

@ -4,7 +4,7 @@
{% block tickets_content %}
<div class="formpage">
<h1>{% trans 'New Ticket' %}</h1>
<h2>{% trans 'New Ticket' %}</h2>
<form class="pure-form pure-form-stacked" action="" method="post">
{% csrf_token %}

@ -4,11 +4,11 @@
{% block tickets_content %}
<div class="formpage">
<h1>{% trans 'Ticket:' %} {{ ticket.subject }}
<h2>{% trans 'Ticket:' %} {{ ticket.subject }}
{% if not ticket.is_open %}
<b>[{% trans 'closed' %}]</b>
{% endif %}
</h1>
</h2>
<div class="ticket-messages">
{% for message in ticket_messages %}

Loading…
Cancel
Save