Better frequent questions, tiny css improvements
parent
5cf77af233
commit
2fc3a0274c
@ -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())
|
||||
|
@ -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>
|
||||
{% 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>
|
||||
{% 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>
|
||||
{% trans 'Self-Diagnosis' %}
|
||||
</a>
|
||||
</li>
|
||||
<li><a href="/page/privacy">
|
||||
<i class="fa fa-shield fa-fw" aria-hidden="true"></i>
|
||||
{% 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>
|
||||
{% trans 'Android' %}
|
||||
</a></li>
|
||||
<li><a href="/page/install-windows">
|
||||
<i class="fa fa-windows fa-fw" aria-hidden="true"></i>
|
||||
{% trans 'Windows' %}
|
||||
</a></li>
|
||||
<li><a href="/page/install-gnulinux">
|
||||
<i class="fa fa-linux fa-fw" aria-hidden="true"></i>
|
||||
{% trans 'GNU/Linux' %}
|
||||
</a></li>
|
||||
<li><a href="/page/install-osx">
|
||||
<i class="fa fa-apple fa-fw" aria-hidden="true"></i>
|
||||
{% trans 'OS X' %}
|
||||
</a></li>
|
||||
<li><a href="/page/install-chromeos">
|
||||
<i class="fa fa-chrome fa-fw" aria-hidden="true"></i>
|
||||
{% 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>
|
||||
{% 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 %}
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
Loading…
Reference in New Issue