kopia lustrzana https://gitlab.com/marnanel/chapeau
intermediate
rodzic
7cab79775e
commit
e69df8f686
|
@ -53,7 +53,7 @@ class Command(KepiCommand):
|
|||
|
||||
spec = {
|
||||
'type': 'Person',
|
||||
'id': '@'+new_name,
|
||||
'preferredUsername': new_name,
|
||||
}
|
||||
|
||||
logger.debug('Creating object with spec %s',
|
||||
|
|
|
@ -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'),
|
||||
),
|
||||
]
|
|
@ -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):
|
||||
"""
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue