spkrepo

Release v0.1

Spkrepo is a feature rich Synology Package Repository application. It is compatible with DSM 4.2 on onwards and comes with an API, advanced permission management and an admin interface.

Documentation

API

spkrepo exposes a RESTful API and returns standard HTTP Status Codes in all responses. Data is returned as JSON.

Authentication

To access the API, user must be registered, have the developer role and generated an API key from the profile page. The Authorization header is mandatory and must contain the API key as user with no password. If the authentication fails, a 401 Unauthorized is returned.

Warning

For security reasons, only one API key can be valid at a time. Should the API key be compromised, a new one can be generated from the profile page.

Errors

In case of ambiguous error, a detailed explaination is returned in JSON as message

HTTP/1.1 422 UNPROCESSABLE ENTITY
Content-Length: 43
Content-Type: application/json

{
    "message": "Unknown architecture: myarch"
}

Endpoints

POST /api/packages

Post a SPK to the repository.

First a Package is created if not existing already, based on the name. Only users with package_admin role can create new packages, other users must be defined as maintainers to be able to continue.

Then a Version is created with its appropriate relationships if not existing already, based on the package and the version.

Lastly, a Build is created with its appropriate relationships and files saved on the filesystem.

Note

The created Build is not active by default

Example response:

HTTP/1.1 201 CREATED
Content-Length: 97

{
    "architectures": ["88f628x"],
    "firmware": "3.1-1594",
    "package": "btsync",
    "version": "1.4.103-10"
}
Status Codes:

Models

Referential

class spkrepo.models.Architecture(**kwargs)[source]
builds
code
classmethod find(code, syno=False)[source]
from_syno = {'88f6282': '88f628x', '88f6281': '88f628x'}
id
to_syno = {'88f628x': '88f6281'}
class spkrepo.models.Firmware(**kwargs)[source]
build
classmethod find(build)[source]
firmware_string
id
version
class spkrepo.models.Language(**kwargs)[source]
code
classmethod find(code)[source]
id
name
class spkrepo.models.Service(**kwargs)[source]
code
classmethod find(code)[source]
id

Users

class spkrepo.models.User(**kwargs)[source]
active
api_key
authored_packages
confirmed_at
email
github_access_token
id
maintained_packages
password
roles
username
class spkrepo.models.Role(**kwargs)[source]
description
classmethod find(name)[source]
id
name
users

Core

class spkrepo.models.Package(**kwargs)[source]
author
author_user_id
download_count
classmethod find(name)[source]
id
insert_date
maintainers
name
recent_download_count
screenshots
versions
class spkrepo.models.Version(**kwargs)[source]
all_builds_active = <sqlalchemy.sql.elements.BinaryExpression object>
beta = <sqlalchemy.sql.elements.BinaryExpression object>
builds
changelog
conf_conflicts
conf_dependencies
conflicts
dependencies
descriptions
displaynames
distributor
distributor_url
icons
id
insert_date
install_wizard
license
maintainer
maintainer_url
package
package_id
path
report_url
service_dependencies
startable
upgrade_wizard
upstream_version
version
version_string = <sqlalchemy.sql.elements.BinaryExpression object>
class spkrepo.models.Build(**kwargs)[source]
active
architectures
checksum
downloads
extract_size
firmware
firmware_id
classmethod generate_filename(package, version, firmware, architectures)[source]
id
insert_date
md5
path
publisher
publisher_user_id
save(stream)[source]
version
version_id

Data

class spkrepo.models.Screenshot(**kwargs)[source]
id
package
package_id
path
save(stream)[source]
class spkrepo.models.DisplayName(**kwargs)[source]
displayname
language
language_id
version_id
class spkrepo.models.Description(**kwargs)[source]
description
language
language_id
version_id
class spkrepo.models.Icon(**kwargs)[source]
id
path
save(stream)[source]
size
version
version_id

Statistics

class spkrepo.models.Download(**kwargs)[source]
architecture
architecture_id
build
build_id
date
firmware_build
id
ip_address
user_agent

Utilities

class spkrepo.utils.SPK(stream)[source]

SPK utilities

Parameters:stream (fileobj) – SPK file stream
BOOLEAN_INFO = {'support_conf_folder', 'startable'}

Boolean INFO keys

REQUIRED_INFO = {'package', 'displayname', 'version', 'arch', 'firmware', 'description'}

Required keys in the INFO file

SIGNATURE_FILENAME = 'syno_signature.asc'

Signature filename

conf_filename_re = re.compile('^conf/.+$')

Regex for files in conf

icon_filename_re = re.compile('^PACKAGE_ICON(?:_(?P<size>120|256))?\\.PNG$')

Regex for icons in files

icon_info_re = re.compile('^package_icon(?:_(?P<size>120|256))?$')

Regex for icons in INFO

info_line_re = re.compile('^(?P<key>\\w+)="(?P<value>.*)"$', re.MULTILINE)

Regex for a line of the INFO file

package_re = re.compile('^[\\w-]+$')

Regex for package in INFO file

script_filename_re = re.compile('^scripts/.+$')

Regex for files in scripts

sign(timestamp_url, gnupghome)[source]

Sign the package

Parameters:
  • timestamp_url – url for the remote timestamping
  • gnupghome – path to the gnupg home
unsign()[source]

Remove the signature file of the package

wizard_filename_re = re.compile('^WIZARD_UIFILES/(?P<process>install|upgrade|uninstall)_uifile(?:_[a-z]{3})?$')

Regex for a wizard filename

Exceptions

class spkrepo.exceptions.SpkrepoError[source]

Base class for exceptions in spkrepo

class spkrepo.exceptions.SPKParseError[source]

Exception raised when SPK parsing fails

class spkrepo.exceptions.SPKSignError[source]

Exception raised when SPK signing fails

Changelog

0.1

release date: 2014-11-30

  • Initial release