Git Product home page Git Product logo

skygeario / skygear-server Goto Github PK

View Code? Open in Web Editor NEW
407.0 29.0 84.0 9.8 MB

Skygear - an open source serverless platform for modern secure app development

Home Page: https://skygear.io

License: Apache License 2.0

Go 95.51% Shell 0.35% HTML 0.02% Makefile 0.60% Nix 0.10% Dockerfile 0.14% TSQL 2.02% PLSQL 0.02% PLpgSQL 0.07% JavaScript 0.67% CSS 0.51%
skygear baas serverless serverless-framework zeromq sdks golang server mobile-development

skygear-server's Introduction

Skygear Logo

Next is the V2 of Skygear that aim to follow

  • Support multi tenant at core, make cloud deploy scalable at first day.
  • Simplify deployment.
  • Give back application lifecycle to cloud code developer and skygear developer.
  • Drop zmq and model against HTTP semantics.
  • Drop v1 Record class

Project structure

.
├── pkg
│   ├── server    <-- original skygear-server code
│   ├── auth
│   ├── gateway
│   └── core
└── cmd
    ├── auth
    │   └── main.go
    └── gateway
        └── main.go

Troubleshooting

If you encounter a build error look like invalid flag in pkg-config --cflags: -Xpreprocessor, export CGO_CFLAGS_ALLOW=-Xpreprocessor.

Dependencies

If you plan to build and run locally, you need to install the following dependencies.

  • pkgconfig
  • vips >= 8.7

If you are on macOS and user of homebrew, you can install them by

brew install pkgconfig vips

Gateway

Migration

To add a new gear

  1. Add db migration to config db
    • Add enabled column to plan table
    • Add version column to app table
  2. Update pkg/gateway/model/app.go with new gear in Gear, App and GetGearVersion.
  3. Update GetAppByDomain in pkg/gateway/db/app.go with the new gear version column.
  4. Update Plan struct and CanAccessGear func in pkg/gateway/model/plan.go
  5. Update GearURLConfig and GetGearURL func in pkg/gateway/config/config.go

DB migration

The following part is about gateway and gears db migration.

If you come from skygear-server 0.x to 1.x, the biggest difference is that gears in skygear next would not support auto db migration in server boot time.

DB migration must be run before server boot up. And since we do not have a full featured db management tool for skygear yet, here is a general guide for new comers of skygear next user.

  1. Create a schema for common gateway.
  2. Create a schema for your app.
  3. Run core and gear(s) migration.

For example, the app name is helloworld and you want to run auth gear .

# Base app_config schema for core gateway
CREATE SCHEMA app_config;
# Create shared schema for apps
# Run the following SQL in any postgresql client, like Postico
CREATE SCHEMA app;

# If you have psql cli
$ psql ${DATABASE_URL} -c "CREATE SCHEMA app;"

# Run core and auth migration
$ make -C migrate migrate MIGRATE_CMD=up DATABASE_URL=${DATABASE_URL} SCHEMA=app

See below sections for more commands about db migration.

Commands

Add a version

# MODULE can be gateway, core, auth...
$ export MODULE=<module_name>
$ export REVISION=<revision_description>
$ make -C migrate add-version MODULE=${MODULE} REVISION=${REVISION}

Check current db version

$ make -C migrate

Dry run the migration

Transaction will be rollback

$ make -C migrate MIGRATE_CMD=up DRY_RUN=1

Run the migration with github source

$ make -C migrate migrate \
    CORE_SOURCE=github://:@skygeario/skygear-server/migrations/core#6918eed \
    AUTH_SOURCE=github://:@skygeario/skygear-server/migrations/auth#6918eed \
    MIGRATE_CMD=up

Running db migration to all apps in cluster (multi-tenant mode)

Run core and auth migrations to apps which auth version in live

$ make -C migrate migrate \
    APP_FILTER_KEY=auth_version \
    APP_FILTER_VALUE=live \
    CONFIG_DATABASE=postgres://postgres:@localhost/postgres?sslmode=disable \
    HOSTNAME_OVERRIDE=localhost \
    MIGRATE_CMD=up

Start migration server in http server mode

  • To start the migration server
$ make -C migrate http
  • Calling the migration server

    POST /migrate
    

    Request example

    {
        "migration": "auth",
        "schema": "app_config",
        "database": "postgres://postgres:@localhost:5432/postgres?sslmode=disable",
        "command": "version"
    }

    Response example

    {
        "result":"1563434450"
    }

License & Copyright

Copyright (c) 2015-present, Oursky Ltd.
All rights reserved.

This source code is licensed under the Apache License version 2.0
found in the LICENSE file in the root directory of this source tree.
An additional grant of patent rights can be found in the PATENTS
file in the same directory.

skygear-server's People

Contributors

b123400 avatar ben181231 avatar blockloop avatar carmenlau avatar cheungpat avatar chpapa avatar david90 avatar garywahaha avatar inizio avatar joyzoursky avatar kaojohnny avatar kiootic avatar lampercy avatar limouren avatar louischan-oursky avatar rickmak avatar rockychan avatar royuen avatar seventhmoon avatar steven-chan avatar tensiuyan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

skygear-server's Issues

Able to query records with acl set to public:false

When a record is set with ACL [{"public": false}], fetching records by a user other than the owner exhibits correct behavior:

$ http localhost:3000 action=record:fetch access_token=5e6f8c43-3f6b-44ce-96c8-59a97525a4ba ids:='["comment/6a4f53e2-8102-4de1-b845-3d0d9249acdc"]'
{
    "result": [
        {
            "_id": "comment/6a4f53e2-8102-4de1-b845-3d0d9249acdc",
            "_type": "error",
            "code": 102,
            "message": "no permission to read",
            "name": "PermissionDenied"
        }
    ]
}

But querying for the record type will return the record:

$ http localhost:3000 action=record:query access_token=5e6f8c43-3f6b-44ce-96c8-59a97525a4ba record_type=comment
{
    "result": [
        {
            "_access": [
                {
                    "level": ""
                }
            ],
            "_created_at": "2016-06-28T05:58:58.174264Z",
            "_created_by": "f25fca56-073e-4b74-8a2f-ca040a085804",
            "_id": "comment/6a4f53e2-8102-4de1-b845-3d0d9249acdc",
            "_ownerID": "f25fca56-073e-4b74-8a2f-ca040a085804",
            "_type": "record",
            "_updated_at": "2016-06-28T05:58:58.174264Z",
            "_updated_by": "f25fca56-073e-4b74-8a2f-ca040a085804",
            "body": "Lovely!",
            "post": {
                "$id": "post/5ec13be4-b701-4502-b26c-a19ee1122180",
                "$type": "ref"
            }
        }
    ]
}
  • Skygear Server Date/Version: 0.12.1
  • Application Platform:
  • Is this a regression?
  • Attached logs, screenshots

Expected Results

Should not return the record because of ACL setting in place.

Actual Results

Returned the record, ignoring ACL setting.

Feature request: Ignoring ACL when master key is used

It is possible to use master key to impersonate another user using the _user_id, but ACL would still apply. The use case is that a maintenance program will want to update records on behalf of a user, but does not want to be restricted by ACL.

MQTT Support

Does skygear-server support MQTT protocol or something similar which consumes less battery on a mobile device?

HTTP headers from plugin handlers are not written to client

My plugin handler returns this:

        resp = Response(json.dumps(output))
        resp.headers.add('X-Total-Count', 100)
        return resp

This appears in the log between skygear-server and plugin

DEBU[0406] Called  ./run_plugin.sh [./run_plugin.sh --subprocess handler spaces] returning: {"result": {"header": {"Content-Length": ["14029"], "X-Total-Count": ["100"]...

But the header is not written to client:

< HTTP/1.1 200 OK
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Origin: *
< Date: Fri, 08 Apr 2016 04:16:29 GMT
< Content-Type: text/plain; charset=utf-8
< Transfer-Encoding: chunked

I think this is because this is how handler is implemented in plugin/handler.go:

    response.Meta = responsePayload.Header
    response.WriteHeader(responsePayload.Status)  # headers written out
    response.Write(responsePayload.Body)  # headers from the plugin added to `http.ResponseWriter` here.

In other words, the headers from plugin are processed after the response writer has already written out the headers.

NULL token saved to DB causing type error on send

For unknown reason, the a NULL token is saved to _device table. And causing type error on sending push notification.

  • Skygear Server Date/Version: v0.10
  • Application Platform: portal user

Expected Results

The NULL will got rejected during save time.

Actual Results

Got following error on calling push:users

{
  "error": {
    "name": "UnexpectedError",
    "code": 10000,
    "message": "panic occurred while handling request: sql: Scan error on column index 2: unsupported driver -> Scan pair: <nil> -> *string"
  }
}

Cannot required skygear in node

require('skygear'); will result error.

  • Skygear Server Date/Version: v0.13
  • Application Platform:
  • Is this a regression?

Expected Results

It works with in process memory storage

Actual Results

Error: Cannot find module 'localStorage'`

Steps to reproduce

  1. npm install skygear
  2. node
  3. require('skygear');

Locking down schema in production mode

In record:save, the schema is automatically extended when there is a new field. This issue should lock down the schema when in production mode (i.e. dev-mode = NO)

  • should not allow client to change schema when not in dev mode
  • the above rule is bypassed when the request is using the master key

Feature Request: logging should use mime.ParseMediaType

logging should use mime.ParseMediaType instead plain string comparison to determine media type.

  • Skygear Server Date/Version: all
  • Application Platform:
  • Is this a regression?
  • Attached logs, screenshots

Expected Results

Should be able to log if Content-Type is application/json charset=utf-8

Actual Results

Content-Type must be application/json otherwise body will not be logged.

notContains is misbehaved

  • Skygear Server Date/Version: 0.12.1
  • Application Platform:
  • Attached logs, screenshots

I have the following code in my js.

const query = new skygear.Query(skygear.Record.extend('options'));
query.notContains('_id', [
    '4eca7009-1567-43ab-9e7f-5ff5aac67150',
    '5e0d95c2-0ea7-4ba9-8234-27ec70ac0266',
    '7372441b-125f-4c26-b0c6-373f29219e00',
    '86d625ff-1391-4a67-9bcb-b1780b0bbde1',
    'dcc9674d-fb53-4038-bf93-7ffb4de94336',
 ]);
 skygear.publicDB.query(query).then((r) => {
    console.log('record', r);
  });

Basically the above query should return no record to me as all the options records' _id are excluded. However, the above query returns all records in options table.

level=debug msg="{\"action\":\"record:query\",\"api_key\":\"village\",\"access_token\":\"f519981d-2d92-4c87-9ac5-6e27d5f748cb\",\"database_id\":\"_public\",\"record_type\":\"options\",\"limit\":50,\"sort\":[],\"include\":{},\"count\":false,\"predicate\":[\"not\",[\"in\",{\"$type\":\"keypath\",\"$val\":\"_id\"},[\"4eca7009-1567-43ab-9e7f-5ff5aac67150\",\"5e0d95c2-0ea7-4ba9-8234-27ec70ac0266\",\"7372441b-125f-4c26-b0c6-373f29219e00\",\"86d625ff-1391-4a67-9bcb-b1780b0bbde1\",\"dcc9674d-fb53-4038-bf93-7ffb4de94336\"]]]}"

The payload received by the server seems fine.

However, it seems the sql is generated incorrectly.

sql="SELECT \"options\".\"value\" as \"value\", \"options\".\"_id\" as \"_id\", \"options\".\"_database_id\" as \"_database_id\", \"options\".\"_owner_id\" as \"_owner_id\", \"options\".\"key\" as \"key\", \"options\".\"_updated_by\" as \"_updated_by\", \"options\".\"_access\" as \"_access\", \"options\".\"_created_at\" as \"_created_at\", \"options\".\"_created_by\" as \"_created_by\", \"options\".\"_updated_at\" as \"_updated_at\" FROM \"app_village\".\"options\" WHERE \"options\".\"_id\" IN ($1,$2,$3,$4,$5) AND (_access @> '[{\"user_id\": \"50667325-4126-4d47-8fbc-27457629a283\"}]' OR _access @> '[{\"public\": true}]' OR _access IS NULL OR _owner_id = $6) AND _database_id = $7 LIMIT 50"

Make access token expiry configurable

Access token expiry time should be configurable under the token-store section :)

The config could look like:

[token-store]
expiry-time = 31556926 # expiry time in seconds
implementation = fs
# other configs goes here

Transient does not work across database boundary

I am using the [email protected] with [email protected].

query.transientInclude does not work across database boundary.
That is, if a query is targeted at privateDB and the transient target is in publicDB, the transient will be null

  • Skygear Server Date/Version: 0.6.1
  • Application Platform: react-native
  • Is this a regression?
  • Attached logs, screenshots

Expected Results

It should be legal to include transient target in publicDB when issuing a query targeting privateDB.

Actual Results

The transient is null

Steps to reproduce

const skygear = require('skygear');
const PubTable = skygear.Record.extend('pub_table');
const PrivTable = skygear.Record.extend('priv_table');

const pubRecord = new PubTable();
const privRecord = new PrivTable({
  pub_ref: new skygear.Reference(pubRecord),
});

skygear.publicDB.save(pubRecord)
.then(() => {
  return skygear.privateDB.save(privRecord);
})
.then(() => {
  const q = new skygear.Query(PrivTable);
  q.transientInclude('pub_ref');
  return skygear.privateDB.query(q);
})
.then((records) => {
  const actualResult = records[0]._transient.pub_ref;
  console.log(`pub_ref is ${actualResult}`); // This prints "pub_ref is null"
});

new user is not assigned with the default role

A new signup user should belong to the default user role.

  • Skygear Server Date/Version: v0.12.0
  • Application Platform:
  • Is this a regression?
  • Attached logs, screenshots

Expected Results

The new user is assigned with default role 'user'

Actual Results

The new user is not assigned with any roles. The table _user_role is empty.

Steps to reproduce

  1. set a default role, e.g. 'user', such that the _role table is like:
    screen shot 2016-06-02 at 11 03 58
  2. sign up a new user
  3. the _user_role table is empty
Script to reproduce:
#!/bin/bash

export SKYGEAR_ENDPOINT=${SKYGEAR_ENDPOINT:=http://localhost:3000}
export SKYGEAR_APIKEY=${SKYGEAR_APIKEY:=apikey}

# create the first user, who will create a default role
USER1_SIGNUP_PAYLOAD='{"action": "auth:signup", "api_key": "'$SKYGEAR_APIKEY'", "username": "testuser1", "email": "[email protected]", "password": "password"}'
SKYGEAR_ACCESS_TOKEN=`curl -X POST $SKYGEAR_ENDPOINT/auth/signup -d "$USER1_SIGNUP_PAYLOAD" | sed "s/.*access_token\": *\"\([^\"]*\)\".*/\1/"`

export SKYGEAR_ACCESS_TOKEN

# create default role 'user', in table `_role` with {'by_default': true}
DEFAULT_ROLE_PAYLOAD='{"action": "role:default", "api_key": "'$SKYGEAR_APIKEY'", "access_token": "'$SKYGEAR_ACCESS_TOKEN'", "roles": ["user"]}'
curl -XPOST $SKYGEAR_ENDPOINT/role/default -d "$DEFAULT_ROLE_PAYLOAD"

# sign up another user, but no records found in table `_user_role`
USER2_SIGNUP_PAYLOAD='{"action": "auth:signup", "api_key": "'$SKYGEAR_APIKEY'", "username": "testuser2", "email": "[email protected]", "password": "password"}'
curl -X POST $SKYGEAR_ENDPOINT/auth/signup -d "$USER2_SIGNUP_PAYLOAD"

Use .env file instead of ini for configuration

The ini file that gcfg read is particularly hard to modify programmatically.

Specifically, the tool that I use to modify the ini file automatically (augtool) generates this:

[plugin catapi]

which gcfg gives me this:

expected subsection name or right bracket

Using yaml, it is easy to manipulate the configuration using any programming language.

Dig the .ini file, use env file. https://github.com/joho/godotenv

Improve plugin transport

Now

  • JSON base64 encode / decode now
  • The interface is messy now

Todo

  • Need to discuss what actually need to do, what interface is expected
  • zmq should bind to array of bytes stream

This is a summary of discussion with cheungpat

Plugin transport aware application data

  • Context
  • Configuration

Plugin transport should not aware following

  • Methods
  • Payload format

Expected Result
No need to modify the transport on adding/modifying plugin feature or changing payload format.

Feature left for transport (if the transport support)

  • routing and delivery message, N x M
  • connectivity state

Modification needed

  • Move away the Hook code to skydb
  • Make RunProvider work on bytes, Logic/marshal should in it application package, like plugin lambda and handler.
  • Make zmq have no relation with JSON!

Provide a way to initial the first admin role

When the developer try to use the role base ACL, he will need to setup the first admin role and admin users in the database in order to make it works.

  • Skygear Server Date/Version: v0.13 13 July

record:query does not check if record field exists

When record:query is called with a query having a non-existent field, the record query will return an UnexpectedError:

const Note = skygear.Record.extend("note");
var query = new skygear.Query(Note);
query.equalTo("id", "note/d5a02b77-cc7a-4f93-8cb9-4806b3762767");
skygear.publicDB.query(query).then(...);

This code would produce the following error message.

{
    status: 500,
    error: {
        code: 10000,
        message: "pq: column note.id does not exist",
        name: "UnexpectedError"
    }
}

There are two choices here:

  • Since we have JIT record schema, one way to do it is to return empty array of records whenever a query includes non-existent fields.
  • Treat the query as bad data, therefore return an error. We can pick BadRequest (not preferred), InvalidArgument (preferred), or we can create a new kind of error like InvalidQuery.

Thanks for @TakLee96 for reporting the issue in SkygearIO/skygear-SDK-JS#22.

Should not overwrite _access if it is not provided in save request payload

Origanal object:

{
    "_access": [
        {
            "level": "read",
            "public": true
        }
    ],
    "_created_at": "2016-04-28T08:14:16.531024Z",
    "_created_by": "f3c547cf-130d-41bc-bc31-64f29dcfc18a",
    "_id": "TailormTailorTranslation/2f596451-06a3-4cec-a7d5-f01df372ad5c",
    "_ownerID": "f3c547cf-130d-41bc-bc31-64f29dcfc18a",
    "_type": "record",
    "_updated_at": "2016-05-25T06:07:21.786447Z",
    "_updated_by": "f3c547cf-130d-41bc-bc31-64f29dcfc18a",
    "address": "Workshop Unit B, 9/F, Wah Wai Industrial Building, No 1-7 Wo Heung St, Fo Tan, Shatin, Hong Kong",
    "description": "1\n2\n3\n4\n5\n6\n\n7",
    "geolocation": {
        "$lat": 22.396428,
        "$lng": 114.109497,
        "$type": "geo"
    },
    "locale": "en-US",
    "page_name": "Carmen Eng",
    "tailor": {
        "$id": "TailormTailor/ff3b6121-ef79-4ce3-a483-2acc26e62d9a",
        "$type": "ref"
    }
}

Update curl:

curl 'http://api.tailorm.dev/record/save' -H 'Pragma: no-cache' -H 'Origin: http://portal.tailorm.dev' -H 'Accept-Encoding: gzip, deflate' -H 'X-Skygear-Access-Token: 3e0add12-f662-4ae3-9936-c5737024816b' -H 'Accept-Language: en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4,zh-TW;q=0.2' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36' -H 'Content-Type: application/json' -H 'Accept: application/json' -H 'Cache-Control: no-cache' -H 'Referer: http://portal.tailorm.dev/details' -H 'Connection: keep-alive' -H 'X-Skygear-API-Key: tailorm-key' --data-binary '{"action":"record:save","api_key":"tailorm-key","access_token":"3e0add12-f662-4ae3-9936-c5737024816b","database_id":"_public","records":[{"_id":"TailormTailorTranslation/2f596451-06a3-4cec-a7d5-f01df372ad5c","page_name":"Carmen Eng","address":"Workshop Unit B, 9/F, Wah Wai Industrial Building, No 1-7 Wo Heung St, Fo Tan, Shatin, Hong Kong","tailor":{"$id":"TailormTailor/ff3b6121-ef79-4ce3-a483-2acc26e62d9a","$type":"ref"},"locale":"en-US"}]}' --compressed

Response:

{
    "result": [
        {
            "_access": null,
            "_created_at": "2016-04-28T08:14:16.531024Z",
            "_created_by": "f3c547cf-130d-41bc-bc31-64f29dcfc18a",
            "_id": "TailormTailorTranslation/2f596451-06a3-4cec-a7d5-f01df372ad5c",
            "_ownerID": "f3c547cf-130d-41bc-bc31-64f29dcfc18a",
            "_type": "record",
            "_updated_at": "2016-05-25T06:07:55.537599Z",
            "_updated_by": "f3c547cf-130d-41bc-bc31-64f29dcfc18a",
            "address": "Workshop Unit B, 9/F, Wah Wai Industrial Building, No 1-7 Wo Heung St, Fo Tan, Shatin, Hong Kong",
            "description": "1\n2\n3\n4\n5\n6\n\n7",
            "geolocation": {
                "$lat": 22.396428,
                "$lng": 114.109497,
                "$type": "geo"
            },
            "locale": "en-US",
            "page_name": "Carmen Eng",
            "tailor": {
                "$id": "TailormTailor/ff3b6121-ef79-4ce3-a483-2acc26e62d9a",
                "$type": "ref"
            }
        }
    ]
}

Modify the dev_only preprocessors to allow overwrite by master-key

Rationale
we are using dev_only preprocessors at two handler now: role and schema. Which is very handy to modify role/schema as wishes during development. But in actual usecase, we also need to do role/schema related operation on production deployment where dev-mode will be off. Currently, we will need to do that at DB level, or turn on dev-mode for a moment. Both way is not desired to make the deployment similar to development.

A better solution will be the preprocessors will allow pass through by following condition:
dev-mode is true ormaster-key is correct

  • Skygear Server Date/Version: v0.13

User Query does not include the roles

When querying user using user:query, currently the response does not include the user's roles:

{
  "result": [
    {
      "data": {
        "_id": "cd612328-3cf3-421f-af0e-474e06f6a9ac",
        "email": "[email protected]",
        "username": ""
      },
      "id": "cd612328-3cf3-421f-af0e-474e06f6a9ac",
      "type": "user"
    }
  ]
}

Case insensitive search on username and email

Skygear-server stores username and email with case preserved. It appears that skygear-server perform case sensitive search on username and email for auth and user discovery.

There is an offline discussion about this and we want to support case preserved username and email while having case insensitive search on these two fields.

Support integer column

e.g. we have a record "food" which has an integer column "tip":

               Table "app.food"
     Column     |            Type             | Modifiers 
----------------+-----------------------------+-----------
 _id            | text                        | not null
 tip            | integer                     | 

I want CRUD to works correctly on "food" records.

The state of affairs is fetch, save and delete works correctly except that for save - when I am trying to supply a value on that integer column, I got an error.

cmd

> curl -X POST -H "Content-Type: application/json" \
  -d @- http://localhost:8080/api <<EOF
{
  "api_key": "API_KEY",
  "database_id": "_public",
  "action": "record:save",
  "access_token": "4075602a-52a0-49d7-95a6-675fa514e319",
  "records": [
    {
      "_id": "food/4c5f6213-a022-4cb4-ad8d-bd85d6282eb5",
      "tip": 999
    }
  ]
}
EOF
{"result":[{"_id":"food/4c5f6213-a022-4cb4-ad8d-bd85d6282eb5","_type":"error","code":10000,"message":"pq: relation \"APP.food_tip_seq\" does not exist","name":"UnexpectedError"}]}

Server Log

DEBU[92908] POST /                                       
DEBU[92908] ------ Header: ------                        
DEBU[92908] Accept: [*/*]                                
DEBU[92908] Content-Type: [application/json]             
DEBU[92908] X-Real-Ip: [127.0.0.1]                       
DEBU[92908] X-Forwarded-For: [127.0.0.1]                 
DEBU[92908] Connection: [close]                          
DEBU[92908] Content-Length: [260]                        
DEBU[92908] User-Agent: [curl/7.43.0]                    
DEBU[92908] ------ Request: ------                       
DEBU[92908] {  "api_key": "API_KEY",  "database_id": "_public",  "action": "record:save",  "access_token": "4075602a-52a0-49d7-95a6-675fa514e319",  "records": [    {      "_id": "food/4c5f6213-a022-4cb4-ad8d-bd85d6282eb5",      "tip": 999    }  ]} 
DEBU[92908] Opening DBConn: {pq com_ufo_api postgres://127.0.0.1/ufo?sslmode=disable} 
DEBU[92908] Get DB OK                                    
WARN[92908] 55d4a56d-87a3-4e13-b9b8-7153ed9325cf         
DEBU[92908] Executed SQL with sql.QueryRowx               args=[55d4a56d-87a3-4e13-b9b8-7153ed9325cf] executionCount=1 sql=SELECT id, username, email, password, auth, array_to_json(array_agg(role_id)) AS roles FROM "APP"."_user" LEFT JOIN "APP"."_user_role" ON id = user_id WHERE id = $1 GROUP BY id
DEBU[92908] data <nil>                                   
DEBU[92908] Working with accessModel RoleBasedAccess     
DEBU[92908] Querying remoteColumnTypes food              
DEBU[92908] Executed SQL with sql.QueryRowx               args=[food APP] executionCount=2 sql=
SELECT c.oid
FROM pg_catalog.pg_class c
     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE c.relname = $1
  AND n.nspname = $2
DEBU[92908] Executed SQL successfully with sql.Queryx     args=[5122931] error=<nil> executionCount=3 sql=
SELECT a.attname,
  pg_catalog.format_type(a.atttypid, a.atttypmod)
FROM pg_catalog.pg_attribute a
WHERE a.attrelid = $1 AND a.attnum > 0 AND NOT a.attisdropped
DEBU[92908] Executed SQL successfully with sql.Queryx     args=[APP food] error=<nil> executionCount=4 sql=SELECT kcu.column_name, ccu.table_name FROM information_schema.table_constraints AS tc JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name WHERE constraint_type = 'FOREIGN KEY' AND tc.table_schema = $1 AND tc.table_name = $2
DEBU[92908] Cache remoteColumnTypes food                 
DEBU[92908] Executed SQL with sql.QueryRowx               args=[ 4c5f6213-a022-4cb4-ad8d-bd85d6282eb5] executionCount=5 sql=SELECT "food"."_id" as "_id", "food"."name" as "name", "food"."category" as "category", "food"."_updated_by" as "_updated_by", "food"."timezone" as "timezone", "food"."_access" as "_access", "food"."featured" as "featured", "food"."allergy" as "allergy", "food"."_created_by" as "_created_by", "food"."menu" as "menu", "food"."_database_id" as "_database_id", "food"."image" as "image", "food"."price" as "price", "food"."_created_at" as "_created_at", "food"."_updated_at" as "_updated_at", "food"."allergens" as "allergens", "food"."availabilities" as "availabilities", "food"."_owner_id" as "_owner_id", "food"."restaurant_id" as "restaurant_id", "food"."description" as "description", "food"."options" as "options", "food"."tip" as "tip" FROM "APP"."food" WHERE _database_id = $1 AND _id = $2
DEBU[92908] map[timezone:Asia/Hong_Kong image:0xc8202883c0 availabilities:[map[to:43200 from:0 price:1800 weekdays:[0 1 2 3 4 5 6] price_currency:usd]] description:Roasted Chicken and Lamb, served in Lebanese Pita bread category:Dessert allergens:[SHELLFISH MOLLUSC PEANUT EGG MILK NUT] restaurant_id:{restaurant/212} options:[map[name:Add Cheese choices:[map[default:true name:Normal Cheese] map[name:Double Cheese price:5.99]] required:false] map[name:Beef Temperature choices:[map[name:Rare] map[name:Medium Rare] map[name:Medium] map[name:Medium Well] map[name:Well Done]] required:true] map[name:Extra Cinnamon Powder choices:[map[name:No Need default:true] map[name:Yes price:0.99]] required:false]] name:Sirloin Steak featured:true allergy: menu:FOOD price:18 tip:999] 
DEBU[92908] Querying remoteColumnTypes food              
DEBU[92908] Executed SQL with sql.QueryRowx               args=[food APP] executionCount=6 sql=
SELECT c.oid
FROM pg_catalog.pg_class c
     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE c.relname = $1
  AND n.nspname = $2
DEBU[92908] Executed SQL successfully with sql.Queryx     args=[5122931] error=<nil> executionCount=7 sql=
SELECT a.attname,
  pg_catalog.format_type(a.atttypid, a.atttypmod)
FROM pg_catalog.pg_attribute a
WHERE a.attrelid = $1 AND a.attnum > 0 AND NOT a.attisdropped
DEBU[92908] Executed SQL successfully with sql.Queryx     args=[APP food] error=<nil> executionCount=8 sql=SELECT kcu.column_name, ccu.table_name FROM information_schema.table_constraints AS tc JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name WHERE constraint_type = 'FOREIGN KEY' AND tc.table_schema = $1 AND tc.table_name = $2
DEBU[92908] Cache remoteColumnTypes food                 
ERRO[92908] Failed to execute SQL with sql.Exec           args=["APP"."food_tip_seq" 999] error=pq: relation "APP.food_tip_seq" does not exist executionCount=9 rowsAffected=0 sql=SELECT setval($1, GREATEST(max("tip"), $2)) FROM "APP"."food";
DEBU[92908] failed to save record                         err=UnexpectedError: pq: relation "APP.food_tip_seq" does not exist recordID=food/4c5f6213-a022-4cb4-ad8d-bd85d6282eb5
DEBU[92908] ------ Response: ------                      
DEBU[92908] {"result":[{"_id":"food/4c5f6213-a022-4cb4-ad8d-bd85d6282eb5","_type":"error","code":10000,"message":"pq: relation \"APP.food_tip_seq\" does not exist","name":"UnexpectedError"}]}

Logging at DEBUG level will freeze the terminal

If we tails the log and try to do something like transfer files between plugin and skygear. Current config is to log the whole transferred payload, which cause the freeze of a terminal

  • Skygear Server Date/Version: v0.12.1
  • Application Platform: OSX

Expected Results

  • While debug message is useful during development, the log of large meaningless payload is annoying. Expecting the logs will truncate itself when it larger than a specific amount.

Multiple users can have device registered with the same device token

This might not be necessarily a problem, but it appears that in this scenario, multiple user might be able to register the same device tokens (for push notification purpose):

  1. Login to user account A
  2. Register device
  3. Logout of user account A
  4. Login to user account B
  5. Register device

IMO the right thing to do is to have the original device having the token removed before registering a new device.

Cannot write record after set record to public read write

Update access to public read write:

curl 'http://api.tailorm.dev/record/save' -H 'Pragma: no-cache' -H 'Origin: http://portal.tailorm.dev' -H 'Accept-Encoding: gzip, deflate' -H 'X-Skygear-Access-Token: 3e0add12-f662-4ae3-9936-c5737024816b' -H 'Accept-Language: en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4,zh-TW;q=0.2' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36' -H 'Content-Type: application/json' -H 'Accept: application/json' -H 'Cache-Control: no-cache' -H 'Referer: http://portal.tailorm.dev/booking/3b766adb-aca3-4cfe-87ea-590dadcc2c5e' -H 'Connection: keep-alive' -H 'X-Skygear-API-Key: tailorm-key' --data-binary '{"action":"record:save","api_key":"tailorm-key","access_token":"3e0add12-f662-4ae3-9936-c5737024816b","database_id":"_public","records":[{"_id":"TailormBooking/3b766adb-aca3-4cfe-87ea-590dadcc2c5e","_access":[{"public":true,"level":"write"}],"notes":""}]}' --compressed

Update access response:

{"result":[{"_access":[{"level":"write","public":true}],"_created_at":"2016-05-12T10:17:03.999031Z","_created_by":"a03266e3-9b73-476a-b1f0-c784bbf43a63","_id":"TailormBooking/3b766adb-aca3-4cfe-87ea-590dadcc2c5e","_ownerID":"a03266e3-9b73-476a-b1f0-c784bbf43a63","_type":"record","_updated_at":"2016-05-26T04:41:25.224553Z","_updated_by":"f3c547cf-130d-41bc-bc31-64f29dcfc18a","billing_address":{"address":"","aptNumber":"","billingCountry":"HK","city":"","firstName":"","lastName":"","postalCode":"","state":""},"booking_number":"160399","booking_number_seq":194,"braintree_customer_id":"","braintree_payment_method_nonce":"d2924c9c-bca9-4307-abe6-1c96ab0b7601","braintree_payment_method_token":"fmqkjr","is_review_given":false,"notes":"","price":8000,"price_confirmed":false,"ready":false,"remarks":"","status":"booked","tailor_product":{"$id":"TailormTailorProduct/ba6bc7f4-5ec0-4355-95d9-9d0616f2df48","$type":"ref"},"user":{"$id":"TailormUser/a03266e3-9b73-476a-b1f0-c784bbf43a63","$type":"ref"}}]}

User who is not the owner update the record again:

 curl 'http://api.tailorm.dev/record/save' -H 'Pragma: no-cache' -H 'Origin: http://portal.tailorm.dev' -H 'Accept-Encoding: gzip, deflate' -H 'X-Skygear-Access-Token: 3e0add12-f662-4ae3-9936-c5737024816b' -H 'Accept-Language: en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4,zh-TW;q=0.2' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36' -H 'Content-Type: application/json' -H 'Accept: application/json' -H 'Cache-Control: no-cache' -H 'Referer: http://portal.tailorm.dev/booking/3b766adb-aca3-4cfe-87ea-590dadcc2c5e' -H 'Connection: keep-alive' -H 'X-Skygear-API-Key: tailorm-key' --data-binary '{"action":"record:save","api_key":"tailorm-key","access_token":"3e0add12-f662-4ae3-9936-c5737024816b","database_id":"_public","records":[{"_id":"TailormBooking/3b766adb-aca3-4cfe-87ea-590dadcc2c5e","_access":[{"public":true,"level":"write"}],"notes":""}]}' --compressed

PermissionDenied:

{"result":[{"_id":"TailormBooking/3b766adb-aca3-4cfe-87ea-590dadcc2c5e","_type":"error","code":102,"message":"no permission to modify","name":"PermissionDenied"}]}

Skygear crash when deleting device token

  • Skygear Server v0.6.1

Error log:

panic: want 1 rows updated, got 4

goroutine 13 [running]:
github.com/oursky/skygear/skydb/pq.(*conn).DeleteDeviceByToken(0xc8204fa6e0, 0xc8203df980, 0x40, 0xececf9ed4, 0x0, 0x1083a60, 0x0, 0x0)
    /go/src/github.com/oursky/skygear/skydb/pq/device.go:133 +0x4f4
github.com/oursky/skygear/push.(*APNSPusher).recvFeedback(0xc82017eba0)
    /go/src/github.com/oursky/skygear/push/apns.go:125 +0x40a
github.com/oursky/skygear/push.(*APNSPusher).RunFeedback(0xc82017eba0)
    /go/src/github.com/oursky/skygear/push/apns.go:104 +0x3e7
created by main.initAPNSPusher
    /go/src/github.com/oursky/skygear/main.go:304 +0x1b8

goroutine 1 [IO wait, 2 minutes]:
net.runtime_pollWait(0x7f651e8d1c40, 0x72, 0xc820018150)
    /usr/local/go/src/runtime/netpoll.go:157 +0x60
net.(*pollDesc).Wait(0xc820179e20, 0x72, 0x0, 0x0)
    /usr/local/go/src/net/fd_poll_runtime.go:73 +0x3a
net.(*pollDesc).WaitRead(0xc820179e20, 0x0, 0x0)
    /usr/local/go/src/net/fd_poll_runtime.go:78 +0x36
net.(*netFD).accept(0xc820179dc0, 0x0, 0x7f651e8d76b0, 0xc8204f3a00)
    /usr/local/go/src/net/fd_unix.go:408 +0x27c
net.(*TCPListener).AcceptTCP(0xc820028338, 0x45cc30, 0x0, 0x0)
    /usr/local/go/src/net/tcpsock_posix.go:254 +0x4d
net/http.tcpKeepAliveListener.Accept(0xc820028338, 0x0, 0x0, 0x0, 0x0)
    /usr/local/go/src/net/http/server.go:2135 +0x41
net/http.(*Server).Serve(0xc820187e60, 0x7f651e8d7678, 0xc820028338, 0x0, 0x0)
    /usr/local/go/src/net/http/server.go:1887 +0xb3
net/http.(*Server).ListenAndServe(0xc820187e60, 0x0, 0x0)
    /usr/local/go/src/net/http/server.go:1877 +0x136
net/http.ListenAndServe(0xc8200ffbb0, 0x5, 0x0, 0x0, 0x0, 0x0)
    /usr/local/go/src/net/http/server.go:1967 +0x8f
main.main()
    /go/src/github.com/oursky/skygear/main.go:205 +0x39e8

goroutine 17 [syscall, 736 minutes, locked to thread]:
runtime.goexit()
    /usr/local/go/src/runtime/asm_amd64.s:1721 +0x1

goroutine 5 [chan receive, 736 minutes]:
github.com/getsentry/raven-go.(*Client).worker(0xc820080e60)
    /go/src/github.com/getsentry/raven-go/client.go:414 +0x60
created by github.com/getsentry/raven-go.newClient
    /go/src/github.com/getsentry/raven-go/client.go:304 +0x192

goroutine 8 [chan receive]:
github.com/oursky/skygear/skydb/pq.dbInitializer()
    /go/src/github.com/oursky/skygear/skydb/pq/pq.go:104 +0x95
created by github.com/oursky/skygear/skydb/pq.init.2
    /go/src/github.com/oursky/skygear/skydb/pq/pq.go:150 +0x7b

goroutine 9 [chan receive, 736 minutes]:
github.com/getsentry/raven-go.(*Client).worker(0xc820081ae0)
    /go/src/github.com/getsentry/raven-go/client.go:414 +0x60
created by github.com/getsentry/raven-go.newClient
    /go/src/github.com/getsentry/raven-go/client.go:304 +0x192

goroutine 10 [chan receive, 736 minutes]:
database/sql.(*DB).connectionOpener(0xc820081b80)
    /usr/local/go/src/database/sql/sql.go:634 +0x45
created by database/sql.Open
    /usr/local/go/src/database/sql/sql.go:481 +0x336

goroutine 11 [select, 58 minutes]:
github.com/timehop/apns.(*Client).runLoop(0xc820152020)
    /go/src/github.com/timehop/apns/client.go:153 +0x970
created by github.com/timehop/apns.newClientWithConn
    /go/src/github.com/timehop/apns/client.go:46 +0x148

goroutine 12 [chan receive, 736 minutes]:
github.com/oursky/skygear/push.(*APNSPusher).Run(0xc82017eba0)
    /go/src/github.com/oursky/skygear/push/apns.go:80 +0xa0
created by main.initAPNSPusher
    /go/src/github.com/oursky/skygear/main.go:303 +0x196

goroutine 14 [select, 2 minutes]:
github.com/oursky/skygear/subscription.(*Service).Run(0xc820185660)
    /go/src/github.com/oursky/skygear/subscription/service.go:36 +0x7ee
created by main.initSubscription
    /go/src/github.com/oursky/skygear/main.go:324 +0x396

goroutine 27 [select, 2 minutes]:
github.com/oursky/skygear/pubsub.(*Hub).run(0xc820181fc0)
    /go/src/github.com/oursky/skygear/pubsub/hub.go:43 +0x634
created by github.com/oursky/skygear/pubsub.NewWsPubsub
    /go/src/github.com/oursky/skygear/pubsub/ws.go:49 +0x33e

goroutine 37530 [IO wait, 58 minutes]:
net.runtime_pollWait(0x7f651e8d1880, 0x72, 0xc820018150)
    /usr/local/go/src/runtime/netpoll.go:157 +0x60
net.(*pollDesc).Wait(0xc820281720, 0x72, 0x0, 0x0)
    /usr/local/go/src/net/fd_poll_runtime.go:73 +0x3a
net.(*pollDesc).WaitRead(0xc820281720, 0x0, 0x0)
    /usr/local/go/src/net/fd_poll_runtime.go:78 +0x36
net.(*netFD).Read(0xc8202816c0, 0xc820087800, 0x400, 0x400, 0x0, 0x7f651e8cc050, 0xc820018150)
    /usr/local/go/src/net/fd_unix.go:232 +0x23a
net.(*conn).Read(0xc820521978, 0xc820087800, 0x400, 0x400, 0x0, 0x0, 0x0)
    /usr/local/go/src/net/net.go:172 +0xe4
crypto/tls.(*block).readFromUntil(0xc820399a10, 0x7f651e8d2000, 0xc820521978, 0x5, 0x0, 0x0)
    /usr/local/go/src/crypto/tls/conn.go:455 +0xcc
crypto/tls.(*Conn).readRecord(0xc82057a2c0, 0xc72e17, 0x0, 0x0)
    /usr/local/go/src/crypto/tls/conn.go:540 +0x2d1
crypto/tls.(*Conn).Read(0xc82057a2c0, 0xc8204629c0, 0x6, 0x6, 0x0, 0x0, 0x0)
    /usr/local/go/src/crypto/tls/conn.go:901 +0x167
github.com/timehop/apns.(*Conn).Read(0xc82014a360, 0xc8204629c0, 0x6, 0x6, 0x6, 0x0, 0x0)
    /go/src/github.com/timehop/apns/conn.go:88 +0x6a
github.com/timehop/apns.readErrs.func1(0xc82014a360, 0xc8205384e0)
    /go/src/github.com/timehop/apns/client.go:208 +0x7f
created by github.com/timehop/apns.readErrs
    /go/src/github.com/timehop/apns/client.go:216 +0x5d

goroutine 28 [select, 736 minutes]:
github.com/oursky/skygear/pubsub.(*Hub).run(0xc820181480)
    /go/src/github.com/oursky/skygear/pubsub/hub.go:43 +0x634
created by github.com/oursky/skygear/pubsub.NewWsPubsub
    /go/src/github.com/oursky/skygear/pubsub/ws.go:49 +0x33e

goroutine 25 [IO wait, 2 minutes]:
net.runtime_pollWait(0x7f651e8d1d00, 0x72, 0xc820018150)
    /usr/local/go/src/runtime/netpoll.go:157 +0x60
net.(*pollDesc).Wait(0xc8201786f0, 0x72, 0x0, 0x0)
    /usr/local/go/src/net/fd_poll_runtime.go:73 +0x3a
net.(*pollDesc).WaitRead(0xc8201786f0, 0x0, 0x0)
    /usr/local/go/src/net/fd_poll_runtime.go:78 +0x36
net.(*netFD).Read(0xc820178690, 0xc82011b000, 0x1000, 0x1000, 0x0, 0x7f651e8cc050, 0xc820018150)
    /usr/local/go/src/net/fd_unix.go:232 +0x23a
net.(*conn).Read(0xc820028268, 0xc82011b000, 0x1000, 0x1000, 0x0, 0x0, 0x0)
    /usr/local/go/src/net/net.go:172 +0xe4
bufio.(*Reader).fill(0xc8201867e0)
    /usr/local/go/src/bufio/bufio.go:97 +0x1e9
bufio.(*Reader).Read(0xc8201867e0, 0xc82019c020, 0x5, 0x200, 0x41a787, 0x0, 0x0)
    /usr/local/go/src/bufio/bufio.go:207 +0x260
io.ReadAtLeast(0x7f651e8d2028, 0xc8201867e0, 0xc82019c020, 0x5, 0x200, 0x5, 0x0, 0x0, 0x0)
    /usr/local/go/src/io/io.go:298 +0xe6
io.ReadFull(0x7f651e8d2028, 0xc8201867e0, 0xc82019c020, 0x5, 0x200, 0xc8204e3b00, 0x0, 0x0)
    /usr/local/go/src/io/io.go:316 +0x62
github.com/lib/pq.(*conn).recvMessage(0xc82019c000, 0xc820034f40, 0xc820034f58, 0x0, 0x0)
    /go/src/github.com/lib/pq/conn.go:820 +0x15a
github.com/lib/pq.(*ListenerConn).listenerConnLoop(0xc820181f40, 0x0, 0x0)
    /go/src/github.com/lib/pq/notify.go:135 +0xd7
github.com/lib/pq.(*ListenerConn).listenerConnMain(0xc820181f40)
    /go/src/github.com/lib/pq/notify.go:184 +0x25
created by github.com/lib/pq.NewListenerConn
    /go/src/github.com/lib/pq/notify.go:77 +0x17b

goroutine 22 [chan receive, 736 minutes]:
database/sql.(*DB).connectionOpener(0xc820163ae0)
    /usr/local/go/src/database/sql/sql.go:634 +0x45
created by database/sql.Open
    /usr/local/go/src/database/sql/sql.go:481 +0x336

goroutine 23 [select, 2 minutes]:
github.com/oursky/skygear/skydb/pq.(*recordListener).Listen(0xc820185980)
    /go/src/github.com/oursky/skygear/skydb/pq/listener.go:101 +0x9df
created by github.com/oursky/skygear/skydb/pq.(*conn).Subscribe.func1
    /go/src/github.com/oursky/skygear/skydb/pq/listener.go:29 +0x58

goroutine 24 [chan receive, 2 minutes]:
github.com/lib/pq.(*Listener).listenerConnLoop(0xc820186720)
    /go/src/github.com/lib/pq/notify.go:745 +0x1ee
github.com/lib/pq.(*Listener).listenerMain(0xc820186720)
    /go/src/github.com/lib/pq/notify.go:764 +0x21
created by github.com/lib/pq.NewListener
    /go/src/github.com/lib/pq/notify.go:436 +0x1fa

goroutine 29 [select]:
github.com/robfig/cron.(*Cron).run(0xc820181400)
    /go/src/github.com/robfig/cron/cron.go:152 +0x9eb
created by github.com/robfig/cron.(*Cron).Start
    /go/src/github.com/robfig/cron/cron.go:127 +0x40

goroutine 30 [syscall, locked to thread]:
github.com/zeromq/goczmq._Cfunc_zpoller_wait(0x7f6510001ca0, 0xc8000003e8, 0x0)
    github.com/zeromq/goczmq/_obj/_cgo_gotypes.go:618 +0x3a
github.com/zeromq/goczmq.(*Poller).Wait(0xc8201f25e0, 0x3e8, 0x1083a60)
    /go/src/github.com/zeromq/goczmq/poller.go:87 +0x83
github.com/oursky/skygear/plugin/zmq.(*Broker).Run(0xc8201e62c0)
    /go/src/github.com/oursky/skygear/plugin/zmq/broker.go:76 +0x1124
github.com/oursky/skygear/plugin/zmq.zmqTransportFactory.Open.func1(0xc8201e6300, 0xc8201f5b00, 0xf, 0xc8200fded0, 0xc, 0xc8201e62c0)
    /go/src/github.com/oursky/skygear/plugin/zmq/rpc.go:302 +0x18d
created by github.com/oursky/skygear/plugin/zmq.zmqTransportFactory.Open
    /go/src/github.com/oursky/skygear/plugin/zmq/rpc.go:303 +0x4fb

goroutine 31 [syscall, locked to thread]:
github.com/zeromq/goczmq._Cfunc_zpoller_wait(0x13da500, 0xc8000003e8, 0x0)
    github.com/zeromq/goczmq/_obj/_cgo_gotypes.go:618 +0x3a
github.com/zeromq/goczmq.(*Poller).Wait(0xc8201f2620, 0x3e8, 0x1083a60)
    /go/src/github.com/zeromq/goczmq/poller.go:87 +0x83
github.com/oursky/skygear/plugin/zmq.(*Broker).Run(0xc8201e6380)
    /go/src/github.com/oursky/skygear/plugin/zmq/broker.go:76 +0x1124
github.com/oursky/skygear/plugin/zmq.zmqTransportFactory.Open.func1(0xc8201e63c0, 0xc8201f2440, 0x11, 0xc8200fe9e0, 0xc, 0xc8201e6380)
    /go/src/github.com/oursky/skygear/plugin/zmq/rpc.go:302 +0x18d
created by github.com/oursky/skygear/plugin/zmq.zmqTransportFactory.Open
    /go/src/github.com/oursky/skygear/plugin/zmq/rpc.go:303 +0x4fb

goroutine 32 [syscall, locked to thread]:
github.com/zeromq/goczmq._Cfunc_zpoller_wait(0x7f6508001d10, 0xc8000003e8, 0x0)
    github.com/zeromq/goczmq/_obj/_cgo_gotypes.go:618 +0x3a
github.com/zeromq/goczmq.(*Poller).Wait(0xc8201f2660, 0x3e8, 0x1083a60)
    /go/src/github.com/zeromq/goczmq/poller.go:87 +0x83
github.com/oursky/skygear/plugin/zmq.(*Broker).Run(0xc8201e6440)
    /go/src/github.com/oursky/skygear/plugin/zmq/broker.go:76 +0x1124
github.com/oursky/skygear/plugin/zmq.zmqTransportFactory.Open.func1(0xc8201e6480, 0xc8201f2480, 0x11, 0xc8200ff4f0, 0xc, 0xc8201e6440)
    /go/src/github.com/oursky/skygear/plugin/zmq/rpc.go:302 +0x18d
created by github.com/oursky/skygear/plugin/zmq.zmqTransportFactory.Open
    /go/src/github.com/oursky/skygear/plugin/zmq/rpc.go:303 +0x4fb

goroutine 33 [chan receive, 736 minutes]:
github.com/oursky/skygear/plugin/zmq.(*zmqTransport).RequestInit(0xc8200ecb40)
    /go/src/github.com/oursky/skygear/plugin/zmq/rpc.go:117 +0x77
created by github.com/oursky/skygear/plugin.(*Plugin).Init
    /go/src/github.com/oursky/skygear/plugin/plugin.go:134 +0x28b

goroutine 34 [chan receive, 736 minutes]:
github.com/oursky/skygear/plugin/zmq.(*zmqTransport).RequestInit(0xc8200ecd80)
    /go/src/github.com/oursky/skygear/plugin/zmq/rpc.go:117 +0x77
created by github.com/oursky/skygear/plugin.(*Plugin).Init
    /go/src/github.com/oursky/skygear/plugin/plugin.go:134 +0x28b

goroutine 35 [chan receive, 736 minutes]:
github.com/oursky/skygear/plugin/zmq.(*zmqTransport).RequestInit(0xc8200ecfc0)
    /go/src/github.com/oursky/skygear/plugin/zmq/rpc.go:117 +0x77
created by github.com/oursky/skygear/plugin.(*Plugin).Init
    /go/src/github.com/oursky/skygear/plugin/plugin.go:134 +0x28b

Steps to reproduce

No special action, the last successful action was at 2016-05-19T23:58:07Z

Improve error message of IncompatibleSchema

Current there is an error named IncompatibleSchema with error message "failed to migrate record schema"

However, I think we should give it a more clear error message like "FieldA in TypeX are expected, TypeY received" (or sth like that) so it's more easy for users to debug.

Multiple schema in same postgresql will result migration fails on citext

Try to use two schema under same DB, but it fails on create citext extension.

  • Skygear Server Date/Version: v0.12
  • Application Platform:
  • Is this a regression?

Expected Results

One database will allow multiple skygear schema working.

Actual Results

ERRO[0001] Error executing schema migration "" -> "c0397f15027": pq: type "citext" does not exist 
ERRO[0001] Failed to start skygear: failed to open connection: skydb/pq: unable to migrate database because of an error = skydb/pq: failed to init database: pq: type "citext" does not exist 

Steps to reproduce

  1. init the skygear-server with APP_NAME=first, skygear-server will do the database migration correctly.
  2. Terminate skygear-server
  3. Change the APP_NAME config to second
  4. Try to kick start the skygear-server again, skygear-server will raise migration error

Allow master key to do schema migration

This is to assist when the app is in production.

If this setting is on, the schema shouldn't be updated when seeing new fields in the query.

However if the user is using master key, the schema can be changed. Expecting user could call API / using CLI to do schema migration.

container.signup* function should have an optional parameter to create user profile

We are talking about:

signupAnonymously
signupWithEmail,
singupWithUsername, and
default behaviour for skygear.providers.BaseAuthProvider here.

We should have an optional parameter such as "savePublicUserProfile", default is true and when set to true, we will copy the username, email, and everything else to the User table. (Consider change the name of User table to UserProfile?)

The intention is to provide a default which is easier for new developers of Skygear

Support predicate with keypath to referenced record (joined query)

When Record Type A references Record Type B, we want to define a predicate that compare fields on Record Type B when querying for Record Type A.

For example, If note record have a reference field called note_category pointing to category record, we want to search for note having a category with a particular name:

{
  "record_type": "user",
  "predicate": ["eq", {"$type": "keypath", "$val": "note_category.name"}, "interesting"]
}

This effectively translates to SQL by joining the table note and category.

uuid.go:20: undefined: uuid.CleanHyphen

Following https://docs.skygear.io/get-started, I tried installing the skygear server on OSX, I ran into some trouble when trying to install.

Expected Results

The server to download and install

Actual Results

Aragorn:~ tim$ go get github.com/SkygearIO/skygear-server
# github.com/skygeario/skygear-server/uuid
Projects/go-workspace/src/github.com/skygeario/skygear-server/uuid/uuid.go:20: undefined: uuid.CleanHyphen

Steps to reproduce

  1. #go get github.com/SkygearIO/skygear-server

Server should not panic when using a non-existent auth provider

When calling auth:login with a non-existent auth provider, skygear-server should not panic

  • Skygear Server Date/Version: 0.9.0

Actual Results

time="2016-03-23T10:24:34Z" level=error msg="/go/src/github.com/oursky/skygear/router/errors.go:61 (0x5602e2)
    errorFromRecoveringPanic: log.Errorf(\"%s\", debug.Stack())
/go/src/github.com/oursky/skygear/router/router.go:101 (0x56621b)
    (*Router).ServeHTTP.func1: resp.Err = errorFromRecoveringPanic(r)
/usr/local/go/src/runtime/asm_amd64.s:437 (0x466ace)
    call32: CALLFN(·call32, 32)
/usr/local/go/src/runtime/panic.go:423 (0x437069)
    gopanic: reflectcall(nil, unsafe.Pointer(d.fn), deferArgs(d), uint32(d.siz), uint32(d.siz))
/usr/local/go/src/runtime/panic.go:42 (0x435729)
    panicmem: panic(memoryError)
/usr/local/go/src/runtime/sigpanic_unix.go:24 (0x44be2a)
    sigpanic: panicmem()
/go/src/github.com/oursky/skygear/handler/auth.go:143 (0x50631a)
    (*SignupHandler).Handle: principalID, authData, err := authProvider.Login(p.AuthData)
/go/src/github.com/oursky/skygear/router/router.go:142 (0x5651d2)
    (*Router).ServeHTTP: handler.Handle(payload, &resp)
/usr/local/go/src/net/http/server.go:1699 (0x49b0ad)
    (*ServeMux).ServeHTTP: h.ServeHTTP(w, r)
/go/src/github.com/oursky/skygear/router/logging.go:103 (0x563670)
    (*LoggingMiddleware).ServeHTTP: l.Next.ServeHTTP(rlogger, r)
/usr/local/go/src/net/http/server.go:1862 (0x49babe)
    serverHandler.ServeHTTP: handler.ServeHTTP(rw, req)
/usr/local/go/src/net/http/server.go:1361 (0x49930e)
    (*conn).serve: serverHandler{c.server}.ServeHTTP(w, w.req)
/usr/local/go/src/runtime/asm_amd64.s:1721 (0x468e21)
    goexit: BYTE    $0x90   // NOP
"
time="2016-03-23T10:24:34Z" level=error msg="panic occurred while handling request" recovered="runtime error: invalid memory address or nil pointer dereference"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.