fix_ids
Marnanel Thurman 2020-02-11 00:00:21 +00:00
rodzic 7cab79775e
commit e69df8f686
4 zmienionych plików z 70 dodań i 141 usunięć

Wyświetl plik

@ -53,7 +53,7 @@ class Command(KepiCommand):
spec = {
'type': 'Person',
'id': '@'+new_name,
'preferredUsername': new_name,
}
logger.debug('Creating object with spec %s',

Wyświetl plik

@ -0,0 +1,32 @@
# Generated by Django 2.2.4 on 2020-02-10 23:55
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('bowler_pub', '0004_auto_20200204_0134'),
]
operations = [
migrations.RemoveField(
model_name='acobject',
name='serial',
),
migrations.AddField(
model_name='acactor',
name='f_preferredUsername',
field=models.TextField(default='', help_text='Your username. Something like "alice".', unique=True, verbose_name='preferred username'),
),
migrations.AddField(
model_name='acobject',
name='remote_url',
field=models.URLField(null=True, unique=True),
),
migrations.AlterField(
model_name='acobject',
name='id',
field=models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
]

Wyświetl plik

@ -45,15 +45,6 @@ class KepiManager(PolymorphicManager):
class AcObject(PolymorphicModel):
id = models.CharField(
max_length=255,
primary_key=True,
unique=True,
blank=False,
default=None,
editable=False,
)
objects = KepiManager()
published = models.DateTimeField(
@ -64,42 +55,35 @@ class AcObject(PolymorphicModel):
auto_now = True,
)
serial = models.IntegerField(
default = 0,
remote_url = models.URLField(
unique = True,
null = True,
)
@property
def url(self):
uri = self.uri
if uri is None:
return self.id
return self.remote_url
else:
return uri_to_url(uri)
@property
def uri(self):
if self.id.startswith('/'):
return configured_path('OBJECT_LINK',
number = self.id[1:],
)
elif self.id.startswith('@'):
return configured_path('USER_LINK',
username = self.id[1:],
)
else:
if self.remote_url is not None:
# This doesn't work for remote objects.
return None
@property
def number(self):
if self.is_local:
return self.id[1:]
else:
return None
return configured_path('OBJECT_LINK',
number = self.id,
)
def __str__(self):
result = '[%s %s]' % (
result = '[#%d %s]' % (
self.id,
self.f_type,
)
@ -108,44 +92,9 @@ class AcObject(PolymorphicModel):
@property
def short_id(self):
return self.id
@property
def pretty(self):
result = ''
curly = '{'
items = [
('type', self.f_type),
]
for f, v in sorted(self.activity_form.items()):
if f in ['type']:
continue
items.append( (f,v) )
items.extend( [
('actor', self.f_actor),
] )
for f, v in items:
if not v:
continue
if result:
result += ',\n'
result += '%1s %15s: %s' % (
curly,
f,
v,
)
curly = ''
result += ' }'
result = '#%d' % (
self.id,
)
return result
@ -330,7 +279,7 @@ class AcObject(PolymorphicModel):
@property
def is_local(self):
return self.id and self.id[0] in '@/'
return self.remote_url is not None
def entomb(self):
logger.info('%s: entombing', self)
@ -349,78 +298,6 @@ class AcObject(PolymorphicModel):
self.save()
logger.info('%s: entombed', self)
def _generate_id(self):
"""
Returns a value for "id" on a new object, where
the caller has omitted to supply an "id" value.
The new value should be unique.
If this method returns None, the object will
not be created.
"""
return '/%08x' % (random.randint(0, 0xffffffff),)
def _check_provided_id(self):
"""
Checks self.id to see whether it's valid for
this kind of AcObject. It may normalise the value.
If the value is valid, returns.
If the value is invalid, raises ValueError.
This method is not called if self.id is a valid
URL, because that means it's a remote object
and our naming rules won't apply.
"""
if re.match(LOCAL_NUMBER_REGEXP, self.id,
re.IGNORECASE):
self.id = self.id.lower()
logger.debug('id==%s which is a valid local number',
self.id)
return
raise ValueError("Object IDs begin with a slash "+\
"followed by eight characters from "+\
"0-9 or a-f. "+\
"You gave: "+self.id)
def save(self, *args, **kwargs):
if self.serial==0:
max_so_far = AcObject.objects.filter(
).aggregate(models.Max('serial'))['serial__max']
if max_so_far is None:
max_so_far = 0
self.serial = max_so_far + random.randint(0, 256)
logger.info(' -- max serial so far is %d; using serial %d',
max_so_far, self.serial)
if self.id is None:
self.id = self._generate_id()
if self.id is None:
raise ValueError("You need to specify an id "+\
"on %s objects." % (self.__class__.__name__,))
else:
if re.match(URL_REGEXP, self.id,
re.IGNORECASE):
logger.debug('id==%s which is a valid URL',
self.id)
else:
self._check_provided_id()
try:
super().save(*args, **kwargs)
logger.debug('%s: saved', self)
except IntegrityError as ie:
logger.info('Integrity error on save (%s); failed',
ie)
raise ie
@classmethod
def get_by_url(cls, url):
"""

Wyświetl plik

@ -2,7 +2,8 @@ from django.db import models
from django.conf import settings
from . import acobject, following, collection
import kepi.bowler_pub.crypto as crypto
from kepi.bowler_pub.utils import configured_url, uri_to_url
from kepi.bowler_pub.utils import configured_url, \
configured_path, uri_to_url
import logging
import re
@ -26,6 +27,14 @@ class AcActor(acobject.AcObject):
null=True,
)
f_preferredUsername = models.TextField(
verbose_name='preferred username',
help_text = 'Your username. '+\
'Something like "alice".',
unique = True,
default = '',
)
f_name = models.TextField(
verbose_name='name',
help_text = 'Your name, in human-friendly form. '+\
@ -64,6 +73,17 @@ class AcActor(acobject.AcObject):
verbose_name='header image',
)
@property
def uri(self):
if self.remote_url is not None:
# This doesn't work for remote objects.
return None
return configured_path('USER_LINK',
username = self.f_preferredUsername,
)
def _generate_id(self):
return None