Kategori arşivi: Programlama

Programlama hakkında türkçe bilgiler, ipuçları, kod örnekleri, örnek projeler, sorunlar ve çözümler, fikir alışverişi, düşünceler ve daha fazlası

Django MongoDB Paginator

Mongodb kullananlar django’nun kendi paginatorunu kullandıklarında performans sorunları yaşıyor olabilirler, bu kod ile bu sorunu ortadan kaldırabilirsiniz. Kullanmayı bıraktığımız bu güzel kodumuz sizlerle.

Kendinize göre uyarlamayı ihmal etmeyin, kodumuzda sayfa kaldığı yerden devam etsin diye ufak tefek değişiklikler yapılmıştır.

def mongo_paginator(request, data, paginate_by):
    page = int(request.GET.get("page", 1))
    if len(request.GET) > 0:
        get_value = dict(request.GET)
        if get_value.get("page"):
            del get_value["page"]
        url = "?" + str(urlencode(get_value, doseq=True)) + "&page="
    else:
        url = "?page="
    row_count = int(data.count())
    page_count = int(row_count / paginate_by) + \
        1 if row_count > paginate_by else 1
    pagi = {
        "page_range": range(1, page_count+1),
        "has_other_pages": page_count > 1,
        "number": page,
        "has_previous": page > 1,
        "previous_page_number": page - 1,
        "has_next": page < page_count,
        "next_page_number": page + 1,
        "url": url,
    }

    if request.GET.get("page"):
        if page > 1:
            first = paginate_by * (page - 1)
            last = first + paginate_by
            data = data[first:last]
        elif page == 1:
            data = data[:paginate_by]
    else:
        data = data[:paginate_by]
    return {"data": data, "pagi": pagi}

BONUS

def paginate(queryset, request, paginate_by):
    paginator = Paginator(queryset, paginate_by)
    try:
        datum = paginator.page(request.GET.get("page"))
    except PageNotAnInteger:
        datum = paginator.page(1)
    except EmptyPage:
        datum = paginator.page(paginator.num_pages)
    return datum


def get_page_url(request):
    if len(request.GET) > 1:
        get_value = dict(request.GET)
        if get_value.get("page"):
            del get_value["page"]
        url = "?" + str(urlencode(get_value, doseq=True)) + "&page="
    else:
        url = "?page="
    return url

JavaScript ile Kullanıcı İşlem Yapmıyorsa Sayfa Nasıl Yenilenir?

Blog adresimde uzunca bir süre kullandığım, sayfada hiç bir işlem yapmadan kalan kullanıcılar için sayfayı yenileyen bir javascript kodudur, isteyen arkadaşlar sayfada öylece duran kullanıcıları istediği yere yönlendirebilirler.

Ben 30 saniye olarak belirledim, öylece duran kullanıcılar için sayfa yenileniyor.

<script>
var timeoutInMiliseconds = 30000;
var timeoutId; 
  
function startTimer() { 
    timeoutId = window.setTimeout(doInactive, timeoutInMiliseconds)
}
  
function doInactive() {
	window.location.reload(true)
}

function resetTimer() { 
    window.clearTimeout(timeoutId)
    startTimer();
}

function setupTimers () {
    document.addEventListener("mousemove", resetTimer, false);
    document.addEventListener("mousedown", resetTimer, false);
    document.addEventListener("keypress", resetTimer, false);
    document.addEventListener("touchmove", resetTimer, false);
     
    startTimer();
}
 
document.addEventListener("DOMContentLoaded", function() {
	setupTimers();
});
</script>

PHP’de Cross Site Scripting (XSS) Filtreleme Nasıl Yapılır?

En temel filtreleme şekli

filter_var($input, FILTER_SANITIZE_STRING);

Regexp kullanarak xss ataklarının filtreleme işlemi

function xss_clean($data)
{
        // Fix &entity\n;
        $data = str_replace(array('&amp;','&lt;','&gt;'), array('&amp;amp;','&amp;lt;','&amp;gt;'), $data);
        $data = preg_replace('/(&#*\w+)[\x00-\x20]+;/u', '$1;', $data);
        $data = preg_replace('/(&#x*[0-9A-F]+);*/iu', '$1;', $data);
        $data = html_entity_decode($data, ENT_COMPAT, 'UTF-8');

        // Remove any attribute starting with "on" or xmlns
        $data = preg_replace('#(<[^>]+?[\x00-\x20"\'])(?:on|xmlns)[^>]*+>#iu', '$1>', $data);

        // Remove javascript: and vbscript: protocols
        $data = preg_replace('#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([`\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2nojavascript...', $data);
        $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2novbscript...', $data);
        $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u', '$1=$2nomozbinding...', $data);

        // Only works in IE: <span style="width: expression(alert('Ping!'));"></span>
        $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?expression[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
        $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?behaviour[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
        $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*+>#iu', '$1>', $data);

        // Remove namespaced elements (we do not need them)
        $data = preg_replace('#</*\w+:\w[^>]*+>#i', '', $data);

        do
        {
                // Remove really unwanted tags
                $old_data = $data;
                $data = preg_replace('#</*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|i(?:frame|layer)|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|title|xml)[^>]*+>#i', '', $data);
        }
        while ($old_data !== $data);

        // we are done...
        return $data;
}
final class xCleaner {

    public static function clean( string $html ): string {

        return self::cleanXSS(

            preg_replace(

                [

                    '/\s?<iframe[^>]*?>.*?<\/iframe>\s?/si',
                    '/\s?<style[^>]*?>.*?<\/style>\s?/si',
                    '/\s?<script[^>]*?>.*?<\/script>\s?/si',
                    '#\son\w*="[^"]+"#',

                ],

                [
                    '',
                    '',
                    ''
                ],

                $html

            )

        );

    }

    protected static function hexToSymbols( string $s ): string {

        return html_entity_decode($s, ENT_XML1, 'UTF-8');

    }

    protected static function escape( string $s, string $m = 'attr' ): string {

        preg_match_all('/data:\w+\/([a-zA-Z]*);base64,(?!_#_#_)([^)\'"]*)/mi', $s, $b64, PREG_OFFSET_CAPTURE);

        if( count( array_filter( $b64 ) ) > 0 ) {

            switch( $m ) {

                case 'attr':

                    $xclean = self::cleanXSS(

                                        urldecode(

                                            base64_decode(

                                                $b64[ 2 ][ 0 ][ 0 ]

                                            )

                                        )

                                );

                    break;

                case 'tag':

                    $xclean = self::cleanTagInnerXSS(

                                        urldecode(

                                            base64_decode(

                                                $b64[ 2 ][ 0 ][ 0 ]

                                            )

                                        )

                                );

                    break;

            }

            return substr_replace(

                $s,

                '_#_#_'. base64_encode( $xclean ),

                $b64[ 2 ][ 0 ][ 1 ],

                strlen( $b64[ 2 ][ 0 ][ 0 ] )

            );

        }
        else {

            return $s;

        }

    }

    protected static function cleanXSS( string $s ): string {

        // base64 injection prevention
        $st = self::escape( $s, 'attr' );

        return preg_replace([

                // JSON unicode
                '/\\\\u?{?([a-f0-9]{4,}?)}?/mi',                                                                    // [1] unicode JSON clean

                // Data b64 safe
                '/\*\w*\*/mi',                                                                                            // [2] unicode simple clean

                // Malware payloads
                '/:?e[\s]*x[\s]*p[\s]*r[\s]*e[\s]*s[\s]*s[\s]*i[\s]*o[\s]*n[\s]*(:|;|,)?\w*/mi',    // [3]  (:expression) evalution
                '/l[\s]*i[\s]*v[\s]*e[\s]*s[\s]*c[\s]*r[\s]*i[\s]*p[\s]*t[\s]*(:|;|,)?\w*/mi',         // [4]  (livescript:) evalution
                '/j[\s]*s[\s]*c[\s]*r[\s]*i[\s]*p[\s]*t[\s]*(:|;|,)?\w*/mi',                                 // [5]  (jscript:) evalution
                '/j[\s]*a[\s]*v[\s]*a[\s]*s[\s]*c[\s]*r[\s]*i[\s]*p[\s]*t[\s]*(:|;|,)?\w*/mi',       // [6]  (javascript:) evalution
                '/b[\s]*e[\s]*h[\s]*a[\s]*v[\s]*i[\s]*o[\s]*r[\s]*(:|;|,)?\w*/mi',                     // [7]  (behavior:) evalution
                '/v[\s]*b[\s]*s[\s]*c[\s]*r[\s]*i[\s]*p[\s]*t[\s]*(:|;|,)?\w*/mi',                      // [8]  (vsbscript:) evalution
                '/v[\s]*b[\s]*s[\s]*(:|;|,)?\w*/mi',                                                              // [9]  (vbs:) evalution
                '/e[\s]*c[\s]*m[\s]*a[\s]*s[\s]*c[\s]*r[\s]*i[\s]*p[\s]*t*(:|;|,)?\w*/mi',        // [10] (ecmascript:) possible ES evalution
                '/b[\s]*i[\s]*n[\s]*d[\s]*i[\s]*n[\s]*g*(:|;|,)?\w*/mi',                                 // [11] (-binding) payload
                '/\+\/v(8|9|\+|\/)?/mi',                                                                          // [12] (UTF-7 mutation)

                // Some entities
                '/&{\w*}\w*/mi',                                                                                   // [13] html entites clenup
                '/&#\d+;?/m',                                                                                      // [14] html entites clenup

                // Script tag encoding mutation issue
                '/\¼\/?\w*\¾\w*/mi',                                                                         // [21] mutation KOI-8
                '/\+ADw-\/?\w*\+AD4-\w*/mi',                                                         // [22] mutation old encodings

                '/\/*?%00*?\//m',

                // base64 escaped
                '/_#_#_/mi',                                                                                       // [23] base64 escaped marker cleanup
             
            ],

            // Replacements steps :: 23
            ['&#x$1;', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''],

            str_ireplace(

                ['\u0', '&colon;', '&tab;', '&newline;'],
                ['
final class xCleaner {
public static function clean( string $html ): string {
return self::cleanXSS(
preg_replace(
[
'/\s?<iframe[^>]*?>.*?<\/iframe>\s?/si',
'/\s?<style[^>]*?>.*?<\/style>\s?/si',
'/\s?<script[^>]*?>.*?<\/script>\s?/si',
'#\son\w*="[^"]+"#',
],
[
'',
'',
''
],
$html
)
);
}
protected static function hexToSymbols( string $s ): string {
return html_entity_decode($s, ENT_XML1, 'UTF-8');
}
protected static function escape( string $s, string $m = 'attr' ): string {
preg_match_all('/data:\w+\/([a-zA-Z]*);base64,(?!_#_#_)([^)\'"]*)/mi', $s, $b64, PREG_OFFSET_CAPTURE);
if( count( array_filter( $b64 ) ) > 0 ) {
switch( $m ) {
case 'attr':
$xclean = self::cleanXSS(
urldecode(
base64_decode(
$b64[ 2 ][ 0 ][ 0 ]
)
)
);
break;
case 'tag':
$xclean = self::cleanTagInnerXSS(
urldecode(
base64_decode(
$b64[ 2 ][ 0 ][ 0 ]
)
)
);
break;
}
return substr_replace(
$s,
'_#_#_'. base64_encode( $xclean ),
$b64[ 2 ][ 0 ][ 1 ],
strlen( $b64[ 2 ][ 0 ][ 0 ] )
);
}
else {
return $s;
}
}
protected static function cleanXSS( string $s ): string {
// base64 injection prevention
$st = self::escape( $s, 'attr' );
return preg_replace([
// JSON unicode
'/\\\\u?{?([a-f0-9]{4,}?)}?/mi',                                                                    // [1] unicode JSON clean
// Data b64 safe
'/\*\w*\*/mi',                                                                                            // [2] unicode simple clean
// Malware payloads
'/:?e[\s]*x[\s]*p[\s]*r[\s]*e[\s]*s[\s]*s[\s]*i[\s]*o[\s]*n[\s]*(:|;|,)?\w*/mi',    // [3]  (:expression) evalution
'/l[\s]*i[\s]*v[\s]*e[\s]*s[\s]*c[\s]*r[\s]*i[\s]*p[\s]*t[\s]*(:|;|,)?\w*/mi',         // [4]  (livescript:) evalution
'/j[\s]*s[\s]*c[\s]*r[\s]*i[\s]*p[\s]*t[\s]*(:|;|,)?\w*/mi',                                 // [5]  (jscript:) evalution
'/j[\s]*a[\s]*v[\s]*a[\s]*s[\s]*c[\s]*r[\s]*i[\s]*p[\s]*t[\s]*(:|;|,)?\w*/mi',       // [6]  (javascript:) evalution
'/b[\s]*e[\s]*h[\s]*a[\s]*v[\s]*i[\s]*o[\s]*r[\s]*(:|;|,)?\w*/mi',                     // [7]  (behavior:) evalution
'/v[\s]*b[\s]*s[\s]*c[\s]*r[\s]*i[\s]*p[\s]*t[\s]*(:|;|,)?\w*/mi',                      // [8]  (vsbscript:) evalution
'/v[\s]*b[\s]*s[\s]*(:|;|,)?\w*/mi',                                                              // [9]  (vbs:) evalution
'/e[\s]*c[\s]*m[\s]*a[\s]*s[\s]*c[\s]*r[\s]*i[\s]*p[\s]*t*(:|;|,)?\w*/mi',        // [10] (ecmascript:) possible ES evalution
'/b[\s]*i[\s]*n[\s]*d[\s]*i[\s]*n[\s]*g*(:|;|,)?\w*/mi',                                 // [11] (-binding) payload
'/\+\/v(8|9|\+|\/)?/mi',                                                                          // [12] (UTF-7 mutation)
// Some entities
'/&{\w*}\w*/mi',                                                                                   // [13] html entites clenup
'/&#\d+;?/m',                                                                                      // [14] html entites clenup
// Script tag encoding mutation issue
'/\¼\/?\w*\¾\w*/mi',                                                                         // [21] mutation KOI-8
'/\+ADw-\/?\w*\+AD4-\w*/mi',                                                         // [22] mutation old encodings
'/\/*?%00*?\//m',
// base64 escaped
'/_#_#_/mi',                                                                                       // [23] base64 escaped marker cleanup
],
// Replacements steps :: 23
['&#x$1;', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''],
str_ireplace(
['\u0', '&colon;', '&tab;', '&newline;'],
['\0', ':', '', ''],
// U-HEX prepare step
self::hexToSymbols( $st ))
);
}
}
', ':', '', ''], // U-HEX prepare step self::hexToSymbols( $st )) ); } }

Django’da Parolasız Oturum Açma(Passwordless Authentication) Mekanizması Nasıl Uygulanır?

Sızdırılan parolaların durumları ortada hal böyle olunca alternatif oturum açma mekanizmaları gündeme gelmeye başladı, bunlardan bizimde zamanında kullandığımız yöntemi artık açıklama zamanı geldi. Bu sistemi hali hazırda kullanmayı bıraktık, elimde kalan halini sizlerle paylaşıyorum.

Öncelikli olarak bu sistemde uygulanan yapıda girişler suistimal edilmemesi amacıyla hem tek kullanımlık URL hemde giriş sırasında mail gatewaylerin linkin geçerliliğini devre dışı bırakmaması için hCaptcha ekledik. Tabii bu durum kullanıcıların canını biraz sıktı diyebiliriz, ama güvenlikten ödün vermedik.

Önce kullanıcının sisteme girebilmesi amacıyla bizim belirli bir link oluşturmamız gerekiyor, daha sonra oluşturulan bu link mail aracılığı ile kullanıcıya gidecek oluşturacağımız bu linkin ise belirli bir geçerlilik süresi olacak aynı zamanda link tıklandığında geçerliliğini güvenlik için yitirecek.

class IsLogin(FormView):
    http_method_names = ["get", "post"]
    template_name = "account/login.html"
    email_template_name = "account/mails/login_email.html"
    form_class = UserForm
    success_url = settings.LOGIN_REDIRECT_URL

    def form_valid(self, form):
        try:
            user = Users.objects.get(email=form.cleaned_data["email"], customer__is_active=True)
        except Users.DoesNotExist:
            messages.success(self.request, _("If an account matches the username %s, you should receive an email with magic link." % form.cleaned_data["email"]))
        else:
            current_site = get_current_site(self.request)
            mail_subject = _("Login your account.")
            mail_message = render_to_string(
                self.email_template_name,
                {
                    "user": user,
                    "domain": current_site.domain,
                    "uid": urlsafe_base64_encode(force_bytes(user.pk)),
                    "token": account_activation_token.make_token(user),
                },
            )
            email = EmailMessage(from_email='noreply@mertcangokgoz.com', to=[user.email], subject=mail_subject, body=mail_message)
            email.content_subtype = "html"
            email.send()
            messages.success(self.request, _("If an account matches the username %s, you should receive an email with magic link." % form.cleaned_data["email"]))
        return render(self.request, self.template_name, {"form":self.get_form()})

    def form_invalid(self, form):
        return render(
            self.request, self.template_name, {'form':self.get_form()}
        )

Sisteme giriş yapmış bir kullanıcı tekrar bir şekilde istekte bulunmasın diyede ayrıca kontrol ediyoruz giriş yapmışsa tekrar ilgili alana yönlendiriyoruz.

    def get(self, request, *args, **kwargs):
        if self.request.user.is_authenticated:
            return HttpResponseRedirect(resolve_url(self.success_url))
        return super().get(request, *args, **kwargs)

Eposta oluşturduğumuz ve gerekli bilgileri girdiğimiz noktada ise kullanıcıya özel bir token oluşturuyoruz. Ve bu tokenle birlikte bağlantılı olan verileri ekliyoruz.

mail_message = render_to_string(
self.email_template_name,
 {
    "user": user,
    "domain": current_site.domain,
    "uid": urlsafe_base64_encode(force_bytes(user.pk)),
    "token": account_activation_token.make_token(user),
 },
)

Tokeni ise kullanıcıya göre aşağıdaki şekilde oluşturuyoruz. Burada önemli olan magic_link_secret_key değerinin giriş yapıldıktan sonra otomatik olarak değişmesi olacak.

from django.contrib.auth.tokens import PasswordResetTokenGenerator
from django.utils import six


class TokenGenerator(PasswordResetTokenGenerator):
    def _make_hash_value(self, user, timestamp):

        return (
            six.text_type(user.pk)
            + six.text_type(timestamp)
            + six.text_type(user.magic_link_secret_key)
        )


account_activation_token = TokenGenerator()

Hem OTP hemde Captcha için kullanacağımız sayfamızın ise kodları şu şekilde olacak.

class OTPView(View):
    template_name = "account/otp_login.html"

    def get(self, *args, **kwargs):
        try:
            uid = force_text(urlsafe_base64_decode(self.kwargs.get("uidb64")))
            user = Users.objects.get(pk=uid)
        except:
            messages.error(self.request, _("Link is invalid!"))
            return redirect("/")

        form = OtpCodeForm()
        otp = False

        if not account_activation_token.check_token(user, self.kwargs.get("token")):
            messages.error(self.request, _("Link is invalid!"))
            return redirect("login")

        if not user.otp_active and settings.OTP_IS_ACTIVE and user.is_2fa:
            if account_activation_token.check_token(user, self.kwargs.get("token")):
                return redirect("otp_activation", uidb64 = self.kwargs.get("uidb64"), token = self.kwargs.get("token"))
            else:
                return HttpResponse(_("Link is invalid!"))

        if user.is_2fa:
            if account_activation_token.check_token(user, self.kwargs.get("token")):
                otp = True

        return render(
            self.request, self.template_name, {"form": form, "hcaptcha_sitekey":settings.HCAPTCHA_SITEKEY, "otp":otp}
        )


    def post(self, *args, **kwargs):
        try:
            uid = force_text(urlsafe_base64_decode(self.kwargs.get("uidb64")))
            user = Users.objects.get(pk=uid)
        except:
            messages.error(self.request, _("Link is invalid!"))
            return redirect("/")
        form = OtpCodeForm(data=self.request.POST)
        if not self.request.POST.get("h-captcha-response"):
            messages.warning(self.request, _("Please enter captcha!"))
            return redirect("activate", uidb64 = self.kwargs.get("uidb64"), token = self.kwargs.get("token"))
        payload = { 'secret': settings.HCAPTCHA_SECRET, 'response': self.request.POST["h-captcha-response"] }
        r = requests.post("https://hcaptcha.com/siteverify", data=payload)
        result = json.loads(r.text)
        if not result['success']:
            messages.error(self.request, _("Incorrect Captcha"))
            return redirect("activate", uidb64 = self.kwargs.get("uidb64"), token = self.kwargs.get("token"))

        if user.is_2fa:
            if account_activation_token.check_token(user, self.kwargs.get("token")):
                if form.is_valid():
                    code = form.cleaned_data["code"]
                    totp = TOTP(user.secret_key)
                    if totp.verify(code) and user.customer.is_active:
                        if account_activation_token.check_token(user, self.kwargs.get("token")):
                            login(self.request, user)
                            user.magic_link_secret_key = random_base32()
                            user.save()
                            return redirect("/")
                        else:
                            return redirect("login")
                    else:
                        return HttpResponse(status=401)
                else:
                    messages.error(self.request, _("Incorrect code!"))
            else:
                messages.error(self.request, _("Link is invalid!"))
            return redirect("activate", uidb64 = self.kwargs.get("uidb64"), token = self.kwargs.get("token"))
        elif result['success']:
            if account_activation_token.check_token(user, self.kwargs.get("token")) and user.customer.is_active:
                login(self.request, user)
                user.magic_link_secret_key = random_base32()
                user.save()
                return redirect("/")
            else:
                return redirect("login")
        else:
            messages.error(self.request, str(result))
            return redirect("activate", uidb64 = self.kwargs.get("uidb64"), token = self.kwargs.get("token"))

Kodumuzun tamamı ise şu şekilde oluyor haliyle

from django.conf import settings
from django.contrib import messages
from django.contrib.auth import login, logout
from django.contrib.sites.shortcuts import get_current_site
from django.core.mail import EmailMessage
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import redirect, render, resolve_url
from django.template.loader import render_to_string
from django.utils.encoding import force_bytes, force_text
from django.utils.http import urlsafe_base64_decode, urlsafe_base64_encode
from django.utils.translation import gettext_lazy as _
from django.views.generic import FormView, View

from pyotp import TOTP, random_base32
from .utils.token import account_activation_token

class IsLogin(FormView):
    http_method_names = ["get", "post"]
    template_name = "account/login.html"
    email_template_name = "account/mails/login_email.html"
    form_class = UserForm
    success_url = settings.LOGIN_REDIRECT_URL

    def get(self, request, *args, **kwargs):
        if self.request.user.is_authenticated:
            return HttpResponseRedirect(resolve_url(self.success_url))
        return super().get(request, *args, **kwargs)

    def form_valid(self, form):
        try:
            user = Users.objects.get(email=form.cleaned_data["email"], customer__is_active=True)
        except Users.DoesNotExist:
            messages.success(self.request, _("If an account matches the username %s, you should receive an email with magic link." % form.cleaned_data["email"]))
        else:
            current_site = get_current_site(self.request)
            mail_subject = _("Login your account.")
            mail_message = render_to_string(
                self.email_template_name,
                {
                    "user": user,
                    "domain": current_site.domain,
                    "uid": urlsafe_base64_encode(force_bytes(user.pk)),
                    "token": account_activation_token.make_token(user),
                },
            )
            email = EmailMessage(from_email='noreply@mertcangokgoz.com', to=[user.email], subject=mail_subject, body=mail_message)
            email.content_subtype = "html"
            email.send()
            messages.success(self.request, _("If an account matches the username %s, you should receive an email with magic link." % form.cleaned_data["email"]))
        return render(self.request, self.template_name, {"form":self.get_form()})

    def form_invalid(self, form):
        return render(
            self.request, self.template_name, {'form':self.get_form()}
        )

class OTPView(View):
    template_name = "account/otp_login.html"

    def get(self, *args, **kwargs):
        try:
            uid = force_text(urlsafe_base64_decode(self.kwargs.get("uidb64")))
            user = Users.objects.get(pk=uid)
        except:
            messages.error(self.request, _("Link is invalid!"))
            return redirect("/")

        form = OtpCodeForm()
        otp = False

        if not account_activation_token.check_token(user, self.kwargs.get("token")):
            messages.error(self.request, _("Link is invalid!"))
            return redirect("login")

        if not user.otp_active and settings.OTP_IS_ACTIVE and user.is_2fa:
            if account_activation_token.check_token(user, self.kwargs.get("token")):
                return redirect("otp_activation", uidb64 = self.kwargs.get("uidb64"), token = self.kwargs.get("token"))
            else:
                return HttpResponse(_("Link is invalid!"))

        if user.is_2fa:
            if account_activation_token.check_token(user, self.kwargs.get("token")):
                otp = True

        return render(
            self.request, self.template_name, {"form": form, "hcaptcha_sitekey":settings.HCAPTCHA_SITEKEY, "otp":otp}
        )


    def post(self, *args, **kwargs):
        try:
            uid = force_text(urlsafe_base64_decode(self.kwargs.get("uidb64")))
            user = Users.objects.get(pk=uid)
        except:
            messages.error(self.request, _("Link is invalid!"))
            return redirect("/")
        form = OtpCodeForm(data=self.request.POST)
        if not self.request.POST.get("h-captcha-response"):
            messages.warning(self.request, _("Please enter captcha!"))
            return redirect("activate", uidb64 = self.kwargs.get("uidb64"), token = self.kwargs.get("token"))
        payload = { 'secret': settings.HCAPTCHA_SECRET, 'response': self.request.POST["h-captcha-response"] }
        r = requests.post("https://hcaptcha.com/siteverify", data=payload)
        result = json.loads(r.text)
        if not result['success']:
            messages.error(self.request, _("Incorrect Captcha"))
            return redirect("activate", uidb64 = self.kwargs.get("uidb64"), token = self.kwargs.get("token"))

        if user.is_2fa:
            if account_activation_token.check_token(user, self.kwargs.get("token")):
                if form.is_valid():
                    code = form.cleaned_data["code"]
                    totp = TOTP(user.secret_key)
                    if totp.verify(code) and user.customer.is_active:
                        if account_activation_token.check_token(user, self.kwargs.get("token")):
                            login(self.request, user)
                            user.magic_link_secret_key = random_base32()
                            user.save()
                            return redirect("/")
                        else:
                            return redirect("login")
                    else:
                        return HttpResponse(status=401)
                else:
                    messages.error(self.request, _("Incorrect code!"))
            else:
                messages.error(self.request, _("Link is invalid!"))
            return redirect("activate", uidb64 = self.kwargs.get("uidb64"), token = self.kwargs.get("token"))
        elif result['success']:
            if account_activation_token.check_token(user, self.kwargs.get("token")) and user.customer.is_active:
                login(self.request, user)
                user.magic_link_secret_key = random_base32()
                user.save()
                return redirect("/")
            else:
                return redirect("login")
        else:
            messages.error(self.request, str(result))
            return redirect("activate", uidb64 = self.kwargs.get("uidb64"), token = self.kwargs.get("token"))

TC Kimlik Numarası Nasıl Doğrulanır Ve Üretilir?

Eskiden geliştirmiş olduğum ve kullanmayı bıraktığımız TC Kimlik doğrulama modülünün kodları aşağıdaki gibidir, burada hem TC Kimlik numarası algoritması çalıştırılmakta ve doğrulanmaktadır. Aynı zamanda Suriyeli, Mülteci ve İkame izin almış kişilerinde doğrulama işlemleri yapılabilir.

T.C. Kimlik No, on bir (11) haneden oluşan, Nüfus ve Vatandaşlık İşleri Genel Müdürlüğü tarafından Türkiye vatandaşlarına verilmiş 11 rakamdan oluşan kişiye özgü bir sayıdır. Üzerinde basit bir pariteyle hata bulma özelliği bulunmaktadır; ilk 10 rakamın toplamının birler basamağı, 11. rakamı vermektedir. Bu algoritmayı kullanan oluşturuculara yaklaşık 900 milyon kadar geçerli TC kimlik numarası üretilebilmektedir. Ayrıca; 1, 3, 5, 7 ve 9. rakamın toplamının 7 katı ile 2, 4, 6 ve 8. rakamın toplamının 9 katının toplamının birler basamağı 10. rakamı; 1, 3, 5, 7 ve 9. rakamın toplamının 8 katının birler basamağı 11. rakamı vermektedir.

Wikipedia
# Requirements
#   - pip install zeep 
#
# Mertcan GÖKGÖZ - 2019
#   PrismaCSI
#

import re
import zeep
from zeep.cache import SqliteCache
from zeep.transports import Transport

# Koşullara uyan ama kabul etmememiz gerekenlerin listesi
dont_accept_values = (
    '11111111111',
    '11111111110',
    '22222222220',
    '33333333330',
    '44444444440',
    '55555555550',
    '66666666660',
    '77777777770',
    '88888888880',
    '99999999990'
)

# TC Kimlik numara algoritmaya göre doğrumu
def IsDogruTcMi(tckn: str) -> bool:
    if tckn in dont_accept_values:
        return False
    if len(tckn) != 11:
        return False
    if not tckn.isdigit():
        return False
    if int(tckn[0]) == 0:
        return False
    
    tckn_sumary = (sum([int(tckn[i]) for i in range(0, 9, 2)]) * 7 - sum([int(tckn[i]) for i in range(1, 9, 2)])) % 10

    if tckn_sumary != int(tckn[9]) or(sum([int(tckn[i]) for i in range(10)]) % 10) != int(tckn[10]):
        return False
    return True

# Suriyeli/Mülteci/İkame izni kontrolü
def IsSuriyeliMi(tckn: str) -> bool:
    if tckn.startswith('99') or tckn.startswith('997'):
        return True

transport = Transport(cache=SqliteCache(), timeout=10)

# Türk vatandaşlarını nüfus müdürlüğünden kontrol et
def TRIdentificationNumberValidator(tckn: str, ad: str, soyad: str, dogumyil: int) -> bool:
    ApiHost = 'https://tckimlik.nvi.gov.tr/Service/KPSPublic.asmx?WSDL'
    Service = zeep.Client(wsdl=ApiHost, transport=transport)
    ClientService = Service.service.TCKimlikNoDogrula(tckn, ad.upper(), soyad.upper(), dogumyil)
    return ClientService

# Yabancı uyruklu vatandaşları nüfus müdürlüğünden kontrol et
def ForeignTRIdentificationNumberValidator(tckn: str, ad: str, soyad: str, dogumgun: int, dogumay: int, dogumyil: int) -> bool:
    ApiHost = 'https://tckimlik.nvi.gov.tr/Service/KPSPublicYabanciDogrula.asmx?WSDL'
    Service = zeep.Client(wsdl=ApiHost, transport=transport)
    ClientService = Service.service.YabanciKimlikNoDogrula(tckn, ad.upper(), soyad.upper(), dogumgun, dogumay, dogumyil)
    return ClientService

# Eski Nüfus Cüzdanı Doğrulama
def OldPersonAndIdentificationCardValidator(tckn: str, ad: str, soyad: str, dogumgun: int, dogumay: int, dogumyil: int, serino: str, cuzdan_no: int) -> bool:
    ApiHost = 'https://tckimlik.nvi.gov.tr/Service/KPSPublicV2.asmx?WSDL'
    Service = zeep.Client(wsdl=ApiHost, transport=transport)
    ClientService = Service.service.KisiVeCuzdanDogrula(tckn, ad.upper(), soyad.upper(), dogumgun, dogumay, dogumyil, serino.upper(), cuzdan_no)
    return ClientService

# Yeni Kimlik Kartı Doğrulama
def NewPersonAndIdentificationCardValidator(tckn: str, ad: str, soyad: str, dogumgun: int, dogumay: int, dogumyil: int, tck_seri_no: str) -> bool:
    ApiHost = 'https://tckimlik.nvi.gov.tr/Service/KPSPublicV2.asmx?WSDL'
    Service = zeep.Client(wsdl=ApiHost, transport=transport)
    ClientService = Service.service.KisiVeCuzdanDogrula(tckn, ad.upper(), soyad.upper(), dogumgun, dogumay, dogumyil, tck_seri_no.upper())
    return ClientService

# Türk vatandaşları veya Ikamet izni olanları kontrol et
def tcValidatorClassify(tckn: str, ad: str, soyad: str, dogumgun: int, dogumay: int, dogumyil: int) -> bool:
    if IsSuriyeliMi(tckn):
        return ForeignTRIdentificationNumberValidator(tckn, ad.upper(), soyad.upper(), dogumgun, dogumay, dogumyil)
    else:
        return TRIdentificationNumberValidator(tckn, ad.upper(), soyad.upper(), dogumyil)

Bununla birlikte testler için kullanmak amacıyla geçerli TC kimlik numarası üretmek isterseniz kullanmanız gereken gerekli C kodunu da aşağıya bırakıyorum. Gerekli işlem gücünüz varsa ve ekran kartınızdan destek alırsanız ciddi oranlarda geçerli TC kimlik numarası üretebilirsiniz. Derlemek için gcc -O3 -DMAX_THREAD=8 tcnouretici.c -lpthread komutunu vermeniz yeterli

/*
**
** derleme:
** gcc -O3 -DMAX_THREAD=8 tcnouretici.c -lpthread
**
** i7-4770k 8 thread
** ./a.out > /dev/null  0.02s user 0.01s system 473% cpu 0.008 total
** ./a.out > /dev/null  0.03s user 0.00s system 382% cpu 0.008 total
** ./a.out > /dev/null  0.03s user 0.00s system 484% cpu 0.007 total
** ./a.out > /dev/null  0.03s user 0.00s system 377% cpu 0.008 total
** ./a.out > /dev/null  0.02s user 0.00s system 397% cpu 0.007 total
** ./a.out > /dev/null  0.03s user 0.00s system 454% cpu 0.007 total
** ./a.out > /dev/null  0.03s user 0.00s system 337% cpu 0.008 total
** ./a.out > /dev/null  0.03s user 0.00s system 420% cpu 0.008 total
**
** i7-4770k 1 thread
** ./a.out > /dev/null  0.02s user 0.00s system 79% cpu 0.020 total
** ./a.out > /dev/null  0.02s user 0.00s system 98% cpu 0.020 total
** ./a.out > /dev/null  0.02s user 0.00s system 79% cpu 0.020 total
** ./a.out > /dev/null  0.02s user 0.00s system 79% cpu 0.020 total
** ./a.out > /dev/null  0.02s user 0.00s system 99% cpu 0.020 total
** ./a.out > /dev/null  0.01s user 0.01s system 80% cpu 0.020 total
** ./a.out > /dev/null  0.02s user 0.00s system 80% cpu 0.020 total
** ./a.out > /dev/null  0.02s user 0.00s system 80% cpu 0.020 total
**
*/

#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>

#define MAX_TOTAL  100000000
#ifndef MAX_THREAD
#define MAX_THREAD 2
#endif

struct tcno_t {
    unsigned char tcnos[MAX_TOTAL / MAX_THREAD][12];
};

unsigned long xorshf96(unsigned long *x,
                       unsigned long *y,
                       unsigned long *z) {
    unsigned long t;
    *x ^= *x << 16; *x ^= *x >> 5; *x ^= *x << 1;
    t = *x; *x = *y; *y = *z;
    return *z = t ^ *x ^ *y;
}


void *tcnouret(void *p) {
    unsigned int i, j;
    unsigned long t_toplam, c_toplam;
    struct tcno_t *tcnos = (struct tcno_t *) p;
    unsigned long x = rand(), y = rand(), z = rand();

    for (i = 0; i < MAX_TOTAL / MAX_THREAD; ++i) {
        t_toplam = c_toplam = 0;
        for (j = 0; j < 4; ++j) {
            t_toplam += (tcnos->tcnos[i][j*2] = (xorshf96(&x, &y, &z) % 9) + 1);
            c_toplam += (tcnos->tcnos[i][j*2+1] = xorshf96(&x, &y, &z) % 10);
        }
        // bir tane daha tek gerekli (9. sayi)
        t_toplam += (tcnos->tcnos[i][8] = xorshf96(&x, &y, &z) % 10);

        tcnos->tcnos[i][9] = (t_toplam * 7 - c_toplam) % 10;
        tcnos->tcnos[i][10] = (t_toplam + c_toplam + tcnos->tcnos[i][9]) % 10;

        for (j = 0; j < 11; ++j) {
            tcnos->tcnos[i][j] += 48;
        }
        tcnos->tcnos[i][11] = '\n';
    }

    return p;
}


int main (int argc, char *argv[])
{
    unsigned int i;
    pthread_t threads[MAX_THREAD];
    struct tcno_t *tcnos = (struct tcno_t *)
                           malloc(sizeof(struct tcno_t) * MAX_THREAD);

    srand(time(NULL));

    // threadlari olustur
    for (i = 0; i < MAX_THREAD; ++i) {
        pthread_create(&threads[i], NULL, tcnouret, &tcnos[i]);
    }

    // threadlari main threadle birlestir
    for (i = 0; i < MAX_THREAD; ++i) {
        pthread_join(threads[i], NULL);
        write(1, &tcnos[i], sizeof(struct tcno_t));
    }

    free(tcnos);

    return 0;
}

Wordpress’de Özelleştirilmiş Önizleme Linki Nasıl Oluşturulur?

Wordpress üzerinde Gutenberg kullanan benim gibi arkadaşlar kullandıkları preview linkini cache kurallarına göre özelleştirmek isteyebilirler, bu noktada aşağıdaki gibi functions.php dosyasında yapılacak bir değişiklik ile linki istediğiniz şekilde düzenleyebilme imkanınız mümkün

Zaman damgası eklemeyi unutmadık ve gereken kod şu şekilde oldu

function fix_preview_link_on_draft() {
  echo '<script type="text/javascript">
    jQuery(document).ready(function () {
      const checkPreviewInterval = setInterval(checkPreview, 1000);
      function checkPreview() {
        const editorPreviewButton = jQuery(".edit-post-header-preview__button-external");
        const editorPostSaveDraft = jQuery(".editor-post-save-draft");
        if (editorPostSaveDraft.length && editorPreviewButton.length && editorPreviewButton.attr("href") !== "' . get_preview_post_link() . '&no-cache=' . time() . '" ) {
          editorPreviewButton.attr("href", "' . get_preview_post_link() . '&no-cache=' . time() . '");
          editorPreviewButton.off();
          editorPreviewButton.click(false);
          editorPreviewButton.on("click", function() {
            editorPostSaveDraft.click();
            setTimeout(function() { 
              const win = window.open("' . get_preview_post_link() . '&no-cache=' . time() .'", "_blank");
              if (win) {
                win.focus();
              }
            }, 1000);
          });
        }
      }
    });
  </script>';
}
add_action('admin_footer', 'fix_preview_link_on_draft');

Bundan sonra admin panelinde cache silmeyi unutmayın, daha sonrasında istediğiniz gibi linkleriniz oluşmaya başlayacak.

Python İle Alan Adlarında Malware Kontrolü Nasıl Yapılır?

Malware ve Phishing avlamada en temel olayımızdan bir tanesi dış kaynak güvenlik kontrolü yapmak, tespit ettiğiniz veya tespit edemediğiniz ama kontrol etmek istediğiniz alan adlarını Quad9 veya CleanBrowsing ile kontrol edebilirsiniz.

import dns.resolver  # pip install dnspython
import json


class CheckDns():

    def __init__(self):
        self.datas = {}
        self.quad9()
        self.cleanbrowsing()

    def quad9(self):
        resolver = dns.resolver.Resolver()
        resolver.nameservers = ['9.9.9.9']
        resolver.timeout = 1
        resolver.lifetime = 1

        try:
            resolver.query(self, 'A')
        except dns.resolver.NXDOMAIN:
            self.datas['quad9'] = 1
        except:
            pass

    def cleanbrowsing(self):
        resolver = dns.resolver.Resolver()
        resolver.nameservers = ['185.228.168.9', '185.228.169.9']
        resolver.timeout = 1
        resolver.lifetime = 1

        try:
            resolver.query(self, 'A')
        except dns.resolver.NXDOMAIN:
            self.datas['cleanbrowsing'] = 1
        except:
            pass

    def data(self):
        return json.dumps(self.datas)

Django Dil Çerezleri İçin Arakatman

Projeleri geliştirirken çoklu dil için çalışma yapıyor olabilirsiniz globalleşen dünyada tek dil tek millet gibi kavramlar yok, bunun yerine çoklu dil ve herkese hizmet etmek var. Bu bağlamda kişinin dil ayarlarını tarayıcısına kayıt etmek için aşağıdaki yolu kullanabilirsiniz.

  • 10 yıl geçerli olacak şekilde kayıt edilir.
  • Session’a ayrıca eklenir.
import datetime

from django.utils.translation import LANGUAGE_SESSION_KEY, get_language
from django.conf import settings


class LanguageCookieMiddleware:
    def __call__(self, request, response):
        language = get_language()
        if hasattr(request, 'session'):
            session_language = request.session.get(LANGUAGE_SESSION_KEY, None)
            if session_language and not session_language == language:
                request.session[LANGUAGE_SESSION_KEY] = language
                request.session.save()
        if settings.LANGUAGE_COOKIE_NAME in request.COOKIES and \
                        request.COOKIES[settings.LANGUAGE_COOKIE_NAME] == language:
            return response
        max_age = 365 * 24 * 60 * 60  # 10 yıl
        expires = datetime.datetime.utcnow() + datetime.timedelta(seconds=max_age)
        response.set_cookie(settings.LANGUAGE_COOKIE_NAME, language, expires=expires)
        return response

Django’da Ip Adresinden Timezone Ataması Yapmak

Django üzerinde kullanıcıların IP adreslerine göre zaman dilimlerini değiştirmek kullanıcının bölgesine göre doğru düzgün zamanları göstermek isteyenler aşağıdaki kod parçasını kullanabilirler.

import ipaddress
from django.contrib.gis.geoip2 import GeoIP2
from django.utils.deprecation import MiddlewareMixin

def get_client_ip(request):
    x_forwarded_for = request.META.get("HTTP_X_FORWARDED_FOR")
    if x_forwarded_for:
        ip = x_forwarded_for.split(",")[0]
    elif len(request.META.get("REMOTE_ADDR")) > 6:
        ip = request.META.get("REMOTE_ADDR")
    elif len(request.META.get("CF-Connecting-IP")) > 6:
        ip = request.META.get("CF-Connecting-IP")
    return ip

def is_valid_ip(ip_address):
    try:
        ip = ipaddress.ip_address(ip_address)
        return True
    except ValueError as e:
        return False

def is_local_ip(ip_address):
    try:
        ip = ipaddress.ip_address(ip_address)
        return ip.is_loopback
    except ValueError as e:
        return None

class IPtoTimezoneMiddleware(MiddlewareMixin):
    def process_request(self, request):
        tz = request.session.get('django_timezone')
        if not tz:
            tz = timezone.get_default_timezone()
            client_ip = get_client_ip(request)
            ip_addrs = client_ip.split(',')
            for ip in ip_addrs:
                if is_valid_ip(ip) and not is_local_ip(ip):
                    if ip:
                        tz = GeoIP2().city(str(ip))['time_zone']
                        break
        if tz:
            timezone.activate(tz)
            Users.objects.filter(id=request.user.id).update(timezone=str(tz))
            request.session['django_timezone'] = str(tz)
        else:
            timezone.deactivate()

Matomo Google Arşiv SiteID Düzeltme

Google Analytics kullandınız ve gün geldi benim gibi açık kaynaklı ve google’dan daha güzel veri sunan bir araca geçmek istediniz, Matomo bu noktada tam bir kurtarıcı ve oldukça güzel veriler sunuyor, ancak eski verilerinizi aktarma sırasında sitenizi kullanıyorken aktarım yapıyorsanız siteid değişiyor ve eski verileri göremiyorsunuz.

Bu noktada yapılacak çok basit bir şey var, eski verilerin olduğu tablolarda ID değişikliğine gitmek

UPDATE db_archive_blob_2016_01 SET idsite = 1 WHERE idsite = 2;
UPDATE db_archive_blob_2016_01 SET idsite = 1 WHERE idsite = 3;
UPDATE db_archive_blob_2016_01 SET idsite = 1 WHERE idsite = 4;

UPDATE db_archive_blob_2016_02 SET idsite = 1 WHERE idsite = 2;
UPDATE db_archive_blob_2016_02 SET idsite = 1 WHERE idsite = 3;
UPDATE db_archive_blob_2016_02 SET idsite = 1 WHERE idsite = 4;

UPDATE db_archive_blob_2016_03 SET idsite = 1 WHERE idsite = 2;
UPDATE db_archive_blob_2016_03 SET idsite = 1 WHERE idsite = 3;
UPDATE db_archive_blob_2016_03 SET idsite = 1 WHERE idsite = 4;

UPDATE db_archive_blob_2016_04 SET idsite = 1 WHERE idsite = 2;
UPDATE db_archive_blob_2016_04 SET idsite = 1 WHERE idsite = 3;
UPDATE db_archive_blob_2016_04 SET idsite = 1 WHERE idsite = 4;

UPDATE db_archive_blob_2016_05 SET idsite = 1 WHERE idsite = 2;
UPDATE db_archive_blob_2016_05 SET idsite = 1 WHERE idsite = 3;
UPDATE db_archive_blob_2016_05 SET idsite = 1 WHERE idsite = 4;

UPDATE db_archive_blob_2016_06 SET idsite = 1 WHERE idsite = 2;
UPDATE db_archive_blob_2016_06 SET idsite = 1 WHERE idsite = 3;
UPDATE db_archive_blob_2016_06 SET idsite = 1 WHERE idsite = 4;

UPDATE db_archive_blob_2016_07 SET idsite = 1 WHERE idsite = 2;
UPDATE db_archive_blob_2016_07 SET idsite = 1 WHERE idsite = 3;
UPDATE db_archive_blob_2016_07 SET idsite = 1 WHERE idsite = 4;

UPDATE db_archive_blob_2016_08 SET idsite = 1 WHERE idsite = 2;
UPDATE db_archive_blob_2016_08 SET idsite = 1 WHERE idsite = 3;
UPDATE db_archive_blob_2016_08 SET idsite = 1 WHERE idsite = 4;

UPDATE db_archive_blob_2016_09 SET idsite = 1 WHERE idsite = 2;
UPDATE db_archive_blob_2016_09 SET idsite = 1 WHERE idsite = 3;
UPDATE db_archive_blob_2016_09 SET idsite = 1 WHERE idsite = 4;

UPDATE db_archive_blob_2016_10 SET idsite = 1 WHERE idsite = 2;
UPDATE db_archive_blob_2016_10 SET idsite = 1 WHERE idsite = 3;
UPDATE db_archive_blob_2016_10 SET idsite = 1 WHERE idsite = 4;

UPDATE db_archive_blob_2016_11 SET idsite = 1 WHERE idsite = 2;
UPDATE db_archive_blob_2016_11 SET idsite = 1 WHERE idsite = 3;
UPDATE db_archive_blob_2016_11 SET idsite = 1 WHERE idsite = 4;

UPDATE db_archive_blob_2016_12 SET idsite = 1 WHERE idsite = 2;
UPDATE db_archive_blob_2016_12 SET idsite = 1 WHERE idsite = 3;
UPDATE db_archive_blob_2016_12 SET idsite = 1 WHERE idsite = 4;

UPDATE db_archive_blob_2017_01 SET idsite = 1 WHERE idsite = 2;
UPDATE db_archive_blob_2017_01 SET idsite = 1 WHERE idsite = 3;
UPDATE db_archive_blob_2017_01 SET idsite = 1 WHERE idsite = 4;

UPDATE db_archive_blob_2017_02 SET idsite = 1 WHERE idsite = 2;
UPDATE db_archive_blob_2017_02 SET idsite = 1 WHERE idsite = 3;
UPDATE db_archive_blob_2017_02 SET idsite = 1 WHERE idsite = 4;

UPDATE db_archive_blob_2017_03 SET idsite = 1 WHERE idsite = 2;
UPDATE db_archive_blob_2017_03 SET idsite = 1 WHERE idsite = 3;
UPDATE db_archive_blob_2017_03 SET idsite = 1 WHERE idsite = 4;

UPDATE db_archive_blob_2017_04 SET idsite = 1 WHERE idsite = 2;
UPDATE db_archive_blob_2017_04 SET idsite = 1 WHERE idsite = 3;
UPDATE db_archive_blob_2017_04 SET idsite = 1 WHERE idsite = 4;

UPDATE db_archive_blob_2017_05 SET idsite = 1 WHERE idsite = 2;
UPDATE db_archive_blob_2017_05 SET idsite = 1 WHERE idsite = 3;
UPDATE db_archive_blob_2017_05 SET idsite = 1 WHERE idsite = 4;

UPDATE db_archive_blob_2017_06 SET idsite = 1 WHERE idsite = 2;
UPDATE db_archive_blob_2017_06 SET idsite = 1 WHERE idsite = 3;
UPDATE db_archive_blob_2017_06 SET idsite = 1 WHERE idsite = 4;

UPDATE db_archive_blob_2017_07 SET idsite = 1 WHERE idsite = 2;
UPDATE db_archive_blob_2017_07 SET idsite = 1 WHERE idsite = 3;
UPDATE db_archive_blob_2017_07 SET idsite = 1 WHERE idsite = 4;

UPDATE db_archive_blob_2017_08 SET idsite = 1 WHERE idsite = 2;
UPDATE db_archive_blob_2017_08 SET idsite = 1 WHERE idsite = 3;
UPDATE db_archive_blob_2017_08 SET idsite = 1 WHERE idsite = 4;

UPDATE db_archive_blob_2017_09 SET idsite = 1 WHERE idsite = 2;
UPDATE db_archive_blob_2017_09 SET idsite = 1 WHERE idsite = 3;
UPDATE db_archive_blob_2017_09 SET idsite = 1 WHERE idsite = 4;

UPDATE db_archive_blob_2017_10 SET idsite = 1 WHERE idsite = 2;
UPDATE db_archive_blob_2017_10 SET idsite = 1 WHERE idsite = 3;
UPDATE db_archive_blob_2017_10 SET idsite = 1 WHERE idsite = 4;

UPDATE db_archive_blob_2017_11 SET idsite = 1 WHERE idsite = 2;
UPDATE db_archive_blob_2017_11 SET idsite = 1 WHERE idsite = 3;
UPDATE db_archive_blob_2017_11 SET idsite = 1 WHERE idsite = 4;

UPDATE db_archive_blob_2017_12 SET idsite = 1 WHERE idsite = 2;
UPDATE db_archive_blob_2017_12 SET idsite = 1 WHERE idsite = 3;
UPDATE db_archive_blob_2017_12 SET idsite = 1 WHERE idsite = 4;

Ardından arşivinizi web sitesi üzerinde görebilirsiniz.

Amazon S3 + Django Versiyonlu Statik Dosya Barındırma

Django üzerinde tutulan statik dosyaları versiyonlu bir şekilde tutmak ve Amazon S3 üzerinde barındırmak isteyen arkadaşlarımız bu kodu kullanabilirler. Normalde Django versiyonlanmış Asset desteklemekte ancak direk S3 desteği bulunmamaktadır, bu iş için böyle bir kod işinizi çokça görecektir.

import hashlib
import threading

from django import template
from django.conf import settings
from django.contrib.staticfiles.storage import staticfiles_storage

class UrlCache(object):
    _md5_sum = {}
    _lock = threading.Lock()

    @classmethod
    def get_md5(cls, file):
        try:
            return cls._md5_sum[file]
        except KeyError:
            with cls._lock:
                try:
                    md5 = cls.calc_md5(file)[:8]
                    value = '%s%s?v=%s' % (settings.STATIC_URL, file, md5)
                except OSError:
                    value = settings.STATIC_URL + file
                cls._md5_sum[file] = value
                return value

    @classmethod
    def calc_md5(cls, file_path):
        with staticfiles_storage.open(file_path, 'rb') as fh:
            m = hashlib.md5()
            while True:
                data = fh.read(8192)
                if not data:
                    break
                m.update(data)
            return m.hexdigest()


@register.simple_tag
def md5url(value):
    return UrlCache.get_md5(value)

Kullanabilmek amacıyla STATIC_ROOT tanımlaması yapmayı unutmayınız.