Documentation ¶
Overview ¶
+build generate
Index ¶
- Variables
- type DB
- type Device
- type Devices
- func (db *Devices) Create(groupId string, device *Device) (err error)
- func (db *Devices) Delete(groupId, id string) (err error)
- func (db *Devices) Get(groupId, id string) (device *Device, err error)
- func (db *Devices) List(groupID string) (devices []*Device, err error)
- func (db *Devices) Login(id string) (device *Device, err error)
- func (db *Devices) Update(groupId string, device *Device) (err error)
- type Event
- type Events
- func (db *Events) Create(groupId, deviceId string, events ...*Event) (err error)
- func (db *Events) Delete(groupId, deviceId, id string) (err error)
- func (db *Events) Devices(groupID string) (deviceIds []string, err error)
- func (db *Events) Get(groupId, deviceId, id string) (event *Event, err error)
- func (db *Events) List(groupID, deviceId string) (events []*Event, err error)
- func (db *Events) Update(groupId, deviceId string, event *Event) (err error)
- type Password
- type Place
- type Places
- func (db *Places) Create(groupId string, place *Place) (err error)
- func (db *Places) Delete(groupId, id string) (err error)
- func (db *Places) Get(groupId, id string) (place *Place, err error)
- func (db *Places) List(groupID string) (places []*Place, err error)
- func (db *Places) Update(groupId string, place *Place) (err error)
- type User
- type Users
Constants ¶
This section is empty.
Variables ¶
var ( ErrBadObjectId = errors.New("bad object id") ErrNotFound = mgo.ErrNotFound )
var ( CollectionUsers = "users" CollectionDevices = "devices" CollectionEvents = "events" CollectionPlaces = "places" )
Названия коллекций в хранилище.
var ErrBadPlaceData = errors.New("circle or polygon is require in place")
ErrBadPlaceData возвращается, если ни полигон, ни окружность не заданы в описании места.
Functions ¶
This section is empty.
Types ¶
type DB ¶
type DB struct {
// contains filtered or unexported fields
}
DB описывает хранилище данных и работу с ним.
type Device ¶
type Device struct { // глобальный уникальный идентификатор устройства ID string `bson:"_id" json:"id"` // уникальный идентификатор группы GroupID string `bson:"group,omitempty" json:"group,omitempty"` // отображаемое имя Name string `bson:"name,omitempty" json:"name,omitempty"` // идентификатор типа устройства Type string `bson:"type,omitempty" json:"type,omitempty"` // хеш пароля для авторизации Password Password `bson:"password,omitempty" json:"-"` }
Device описывает информацию об устройстве.
Каждое устройство имеет свой глобальный уникальный идентификатор, который не может повторяться. Плюс, устройство в каждый момент времени может быть привязано только к одной группе пользователей. Это позволяет устройству менять группу, блокируя доступ к старым данным, которые были собраны для другой группы.
Устройству может быть назначен его тип. Это поле используется внутри сервиса для идентификации поддерживаемых устройством возможностей, формата данных и команд.
type Devices ¶
type Devices DB // для обращения к данным об устройствах
func (*Devices) Create ¶
Create создает описание нового устройства, одновременно привязывая его к указанной группе.
func (*Devices) Get ¶
Get возвращает информацию о устройстве с указанным идентификатором, которое привязано к указанной группе.
func (*Devices) List ¶
List возвращает список всех устройств, которые зарегистрированы для данной группы пользователей.
type Event ¶
type Event struct { // уникальный идентификатор записи ID bson.ObjectId `bson:"_id" json:"id"` // уникальный идентификатор устройства DeviceID string `bson:"device" json:"device"` // уникальный идентификатор группы GroupID string `bson:"group,omitempty" json:"group,omitempty"` // временная метка Time time.Time `bson:"time" json:"time"` // тип события: Arrive, Leave, Travel, Check-in, Happen Type string `bson:"type,omitempty" json:"type,omitempty"` // координаты точки Location *geo.Point `bson:"location,omitempty" json:"location,omitempty"` // погрешность координат в метрах Accuracy float64 `bson:"accuracy,omitempty" json:"accuracy,omitempty"` // идентификатор места PlaceID string `bson:"place,omitempty" json:"place,omitempty"` // уровень заряда устройства на тот момент Power uint8 `bson:"power,omitempty" json:"power,omitempty"` // иконка в виде эмодзи Emoji rune `bson:"emoji,omitempty" json:"emoji,omitempty"` // текстовый комментарий к событию Comment string `bson:"comment,omitempty" json:"comment,omitempty"` // дополнительная именованная информация Data map[string]interface{} `bson:"data,omitempty,inline" json:"data,omitempty"` }
Event обычно описывает место, время и событие, которое в нем случилось.
Каждое событие получает свой уникальный идентификатор, назначаемый непосредственно системой. Кроме того, событие привязано к конкретному идентификатору устройства и группе пользователей. Группа пользователей здесь представлена отдельным свойством, не смотря на то, что ее можно достаточно легко получить и из связи с устройством. Это сделано намеренно, чтобы в тех случаях, когда устройство меняет владельца (группу), старые данные о событиях не становились автоматически доступны новым пользователям.
Каждое событие в обязательном порядке характеризуется временем, когда оно произошло. Если при создании описания события время было опущено, то будет автоматически добавлено текущее время сервера.
Тип события задает один из предопределенных типов события. Если не указано, то считается, что тип события не определен.
Каждое событие обычно характеризуется координатами географической точки, в которой оно случилось и дополнительным параметром, указывающим возможный радиус погрешности вычисления данной точки.
Дополнительно, каждое событие может иметь свое описание в текстовом виде и иконку, характеризующую его в некотором визуальном виде. Но с последним обычно тяжело: кто и сколько таких иконок нарисует? Поэтому было принято решения вместо иконки использовать пиктограмму из стандартного набора эмодзи.
И, наконец, последний элемент: именованные поля с произвольным содержимым, позволяющим описать любую дополнительную информацию. В частности, думаю, значения датчиков и сенсоров хорошо и удобно сохранять именно в таком виде. Плюс, всегда можно добавить что-то дополнительно практически в любом удобном формате. Главное, чтобы приложение знало, что потом с этим делать.
type Events ¶
type Events DB // для обращения к данным о событиях
func (*Events) Create ¶
Create добавляет в хранилище описание новых событий с привязкой к устройству.
func (*Events) Devices ¶
Devices возвращает список идентификаторов устройств, данные о которых есть в коллекции событий для данной группы пользователей.
func (*Events) Get ¶
Get возвращает описание события с указанным идентификатором для конкретного устройства из хранилища.
type Password ¶
type Password []byte
Password описывает тип для пароля, хранящегося в виде хеш с использованием алгоритма bcrypt.
func NewPassword ¶
NewPassword возвращает пароль в виде хеш.
type Place ¶
type Place struct { // уникальный идентификатор описания места ID string `bson:"_id,omitempty" json:"id"` // уникальный идентификатор группы GroupID string `bson:"group,omitempty" json:"group,omitempty"` // отображаемое имя Name string `bson:"name,omitempty" json:"name,omitempty"` // географическое описание места как круга Circle *geo.Circle `bson:"circle,omitempty" json:"circle,omitempty"` // географическое описание места в виде полигона Polygon *geo.Polygon `bson:"polygon,omitempty" json:"polygon,omitempty"` // описание в формате GeoJSON для поиска Geo interface{} `bson:"geo" json:"-"` }
Place описывает географическое место, задаваемое для группы пользователей. Такое место может быть описано либо в виде круга, задаваемого координатами центральной точки и радиусом в метрах, либо полигоном. Круг имеет более высокий приоритет, поэтому если задано и то, и другое, то используется именно описание круга.
К сожалению, в формате GeoJSON, который использует для описание географических координат в MongoDB, нет возможности описать круг. Поэтому для работы с ним его приходится трансформировать его в некий многоугольник. Получившийся результат сохраняется в поле Geo и индексируется сервером баз данных. В том же случае, если задан полигон, то его описания просто копируется в это поле без каких-либо изменений.
type Places ¶
type Places DB // для обращения к данным об описании мест
func (*Places) Create ¶
Create добавляет в хранилище описание нового места для группы. Указание группы позволяет дополнительно защитить от ошибок переназначения места для другой группы.
func (*Places) Delete ¶
Delete удаляет описание места с указанным идентификатором из хранилища. Указание группы позволяет дополнительно защитить от ошибок доступа к чужой информации.
func (*Places) Get ¶
Get возвращает описание места по его идентификатору. Кроме идентификатора места, который является уникальным, необходимо так же указывать идентификатор группы — это позволяет дополнительно ограничить даже случайный доступ пользователей к чужой информации.
type User ¶
type User struct { // логин пользователя Login string `bson:"_id" json:"id"` // уникальный идентификатор группы GroupID string `bson:"group,omitempty" json:"group,omitempty"` // отображаемое имя Name string `bson:"name,omitempty" json:"name,omitempty"` // хеш пароля пользователя Password Password `bson:"password" json:"-"` }
User описывает информацию о пользователе.
Логин пользователя является глобальным уникальным идентификатором пользователя и не может повторяться для разных пользователей. Поэтому, скорее всего, удобнее использовать в качестве такого идентификатора e-mail, что избавит от головной боли с уникальностью. Или любой другой идентификатор, который будет действительно глобально уникальным.
Пользователи объединяются в группы, которые разделяют общие ресурсы: имеют доступ к трекам устройств той же группы, общие описания мест и так далее. Пользователь может состоять только в одной группе, но может ее сменить. Идентификатор группы генерируется непосредственно сервером.
Пароль пользователя не хранится в системе, а вместо этого хранится хеш от него: этого вполне достаточно, чтобы иметь возможность проверить правильность введенного пароля, но не позволит его восстановить в исходном виде. В качестве алгоритма хеширования выбран bcrypt (Provos and Mazières's bcrypt adaptive hashing algorithm).
type Users ¶
type Users DB // для обращения к данным о зарегистрированных пользователях
func (*Users) Create ¶
Create создает нового пользователя по его описанию. Поле Login должно быть уникальным, в противном случае возвращается ошибка.
func (*Users) List ¶
List возвращает список всех пользователей, зарегистрированных в указанной группе.