Git Product home page Git Product logo

v6_api's Introduction

GitHub license Build status Github Code scanning Codacy Badge Total alerts Known Vulnerabilities

Development environment

On any OS, install git and docker. Then :

Install

# Download camptocamp.org source code :
git clone https://github.com/c2corg/v6_api
cd v6_api

Run

# the very first call may be quite long, (15 minutes, depending of your bandwith)
# time to make a coffee
docker-compose up

❤️ http://localhost:6543 ❤️

Press CTRL+C to terminate it.

Run the background jobs and syncer scripts

In distinct terminals:

docker-compose exec api make -f config/docker-dev run-background-jobs
docker-compose exec api make -f config/docker-dev run-syncer

Check code quality

In another terminal (docker-compose up must be running) :

./scripts/lint.sh

Run test suite

In another terminal (docker-compose up must be running) :

# full tests, take a while
./scripts/test.sh

# If you need to test a specific point: 
./scripts/test.sh c2corg_api/tests/models/test_book.py

# or:
./scripts/test.sh c2corg_api/tests/models/test_book.py::TestBook

# or even:
./scripts/test.sh c2corg_api/tests/models/test_book.py::TestBook::test_to_archive

Note: if you're using MinGW on Windows, be sure to prefix the command with MSYS_PATH_NOCONV=1

Useful links in wiki

Full info about development environment

v6_api's People

Contributors

antoinemarnat avatar arnaud-morvan avatar asaunier avatar brunobesson avatar cbeauchesne avatar dependabot-preview[bot] avatar dependabot[bot] avatar dkocich avatar elemoine avatar fbunoz avatar florentcadot avatar gberaudo avatar ginold avatar jeanphilippeds avatar julsbreakdown avatar lbesson avatar mfournier avatar momomaniac avatar nayor avatar snyk-bot avatar tormath1 avatar tristan0x avatar tsauerwein avatar

Stargazers

 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

v6_api's Issues

Include associated waypoint title for routes in search index

To do once associations are implemented:

Please note that "route" docs are special: we most likely need to get the routes associated to a given waypoint when searching the waypoint title. But the waypoint title is not embedded in the route name (especially when you have several WP associated to a route).

For instance "Mont Blanc":

waypoint: http://www.camptocamp.org/summits/37355/fr/mont-blanc
routes:
    http://www.camptocamp.org/routes/53781/fr/mont-blanc-arete-des-bosses => name in DB is "Arête des Bosses"
    http://www.camptocamp.org/routes/45967/fr/mont-blanc-par-les-grands-mulets-itineraire-classique => name in DB is "Par les Grands Mulets - Itinéraire classique"

#82 (comment)

Lang/culture consistency

Sometimes we have "culture" in the source code or in the DB cols names. Sometimes "lang".
I feel a bit uncomfortable with this inconsistency. That's a bit confusing.

Shouldn't we grep/replace "culture" by "lang" or "language" everywhere in the API and the UI?

Bad default value for WP activities

Not sure if this is a bug in the API or misformed data on the UI side:

In the WP editing form, no "activities" field is available (yet?). If I edit an existing WP (the form model gets the WP model from the API), an "activities" attributes is available in the model with value "null". Then when I post the model to the API I get the following validation error:

description: ""None" is not iterable"
location: "body"
name: "document.activities"

Returning all attributes when creating a document?

As for now when creating a document, all attributes for all cultures are returned in the JSON response. Ditto when updating?

It might be useful for the mobile app (?) in order to display the full document after creating it.
In the UI, after creating, visitors are redirected to the document "view" page. For instance:
http://www.camptocamp.org/routes/53123/fr/col-du-bonhomme-depuis-notre-dame-de-la-gorge

This page anyway makes an API call to get the document attributes.
In that case it is no use to return all attributes in the doc creation response (the doc id is enough).

Should we be able to add a parameter in the API call to tell if doc attributes must be returned in the creation response?

Use GeoJSON format

Since most of the items returned by the API are georeferenced objects, we should change the output to GeoJSON, not only JSON.

The users migrating script does not update the user_id sequence

I have run the migrating script in demo DB. Users have been imported but then it's not possible to create a new user. The API throws a 500 error

try:
DBSession.flush()
except:
# TODO: log the error for debugging
raise HTTPInternalServerError('Error persisting user')

because an postgresql error is encountered:

 IntegrityError: (psycopg2.IntegrityError) duplicate key value violates unique constraint "user_pkey"
[Fri Dec 11 11:58:42.190775 2015] [wsgi:error] [pid 19562] [remote 10.27.71.4:512] DETAIL:  Key (id)=(15) already exists.
[Fri Dec 11 11:58:42.190784 2015] [wsgi:error] [pid 19562] [remote 10.27.71.4:512]  [SQL: 'INSERT INTO users."user" (username, email, email_validated, moderator, password, temp_password) VALUES (%(username)s, %(email)s, %(email_validated)s, %(moderator)s, %(password)s, %(temp_password)s) RETURNING users."user".id'] [parameters: {'username': u'testc2c', 'email_validated': False, 'moderator': False, 'temp_password': None, 'password': '$2b$12$uOfq/JSAO5RarbMljjhunuC/CklMwYgyJ0wcE8c62ZAhW3n30Kst6', 'email': u'[email protected]'}]

The user_id sequence is indeed set to 15 whereas there is 43776 imported users.

c2corg_main=# select * from users.user_id_seq;
 sequence_name | last_value | start_value | increment_by |      max_value      | min_value | cache_value | log_cnt | is_cycled | is_called 
---------------+------------+-------------+--------------+---------------------+-----------+-------------+---------+-----------+-----------
 user_id_seq   |         15 |           1 |            1 | 9223372036854775807 |         1 |           1 |      32 | f         | t
(1 row)

c2corg_main=# select count(*) from users.user;
 count 
-------
 43776
(1 row)

@gberaudo Could you have a look please? In the meantime I will set the sequence value by hand so that the demo works.

Simplified geometries

Create and store simplified geometries.
These would be returned in search results instead of full geometries.

Store interface language for users

A user should be able to set their preferred interface language which is stored in the database and used every time they access the site.

Server caching

Caching the output of some of the API actions would be relevant to increase the performances of the API. Using dogpile for instance.

I don't think caching the list output is relevant because new items are often added. On the other hand existing documents do not change every day: it's probably a good idea to cache the "get" output (perhaps the history as well).

Auth management

Interesting resources:

We recommend securing your API with OAuth2.

Unlike OAuth1, OAuth2 allows you to manage authentication and resource authorization for any type of application (native mobile app, native tablet app, JavaScript app, server side web app, batch processing…) with or without the resource owner’s consent.
OAuth2 is the de facto standard for securing APIs. Using another technology would slow down your API development and adoption.

Interesting (?) implementations:

Pagination

As for now the collection_get() method returns the whole list of documents, which is not realistic since we have too many items.

Applying a default limit and using pagination technics is then required.

By the way it seems the usual LIMIT/OFFSET approach [1] might cause performance issues when the offset increases (because postgresql has to deal with more rows before slicing them).

Some resources on the web recommend to use the "seek method":
http://leopard.in.ua/2014/10/11/postgresql-paginattion/
http://chrisdone.com/posts/postgresql-pagination
http://winand.at/slides/PaginationDoneTheRightWay.pdf
that does not use OFFSET but a standard WHERE clause combined to LIMIT.

A drawback is that you need to know the id of the last item of the current page to get the x items whose ids are next. It seems it is especially recommended for "infinite scrolling" requests or for "next page" links.

[1] With SQLAlchemy: most likely done using slice() http://docs.sqlalchemy.org/en/rel_1_0/orm/query.html#sqlalchemy.orm.query.Query.slice

Make search index sync more fail-safe

With PR #82 the ElasticSearch index is updated when a new document is added to the database or when a document is modified. But when there is a problem during this sync operation (for example ElastisSearch is down, does not respond, ...) the update is lost and the ElasticSearch index will still have the old version of a document.

To make it fail-safe, we should use a persisted queue:

A queue could be used to do the updates asynchronously. Two strategies are possible:

  • When a document is updated, the api app adds an entry (document_id, local) to the queue. A worker task will consume the queue and update the document in the ElasticSearch index.
  • (Erics idea) The api app adds a message to the queue without specific information. When the worker task receives a message, it retrieves all documents from the database that have changed since the last update and makes the changes to the ElasticSearch index.

Abuse detection

[NEEDS TO BE PRECISED]

We need to figure out what "abusive use" means.

READ:

  • frequency of requests (max x req/s => how to check this?)
  • ??

WRITE:

  • frequency of requests (max x req/s => how to check this?)
  • ??

Add a geom table to archive the geometry field

Since a document geometry may be a bit big, it is a pity to duplicate it in the archives every time someone makes a change in the docs figures.

A solution would be to separate the geometry field into a dedicated geom archives table that would be joined to the other archive tables using a foreign key in the documents_versions table.

To be able to store the geometries of the various doc types (point, line, polygon), using a generic "geometry" type is probably relevant. Would such a field have drawbacks on the other hand?

What about documents with no geometry by nature (books, articles) or with a null geometry? Would they have a null FK in documents_versions?

migration.py chokes on an sqlalchemy.exc.IntegrityError

When running the import script against current production database, it failed with this error:

$ python c2corg_api/scripts/migration/migrate.py
Importing users
Total: 46021 rows
1 of 46021
4004 of 46021
7007 of 46021
10530 of 46021
13013 of 46021
Traceback (most recent call last):
  File "c2corg_api/scripts/migration/migrate.py", line 65, in <module>
    main()
  File "c2corg_api/scripts/migration/migrate.py", line 54, in main
    MigrateUsers(connection_source, session, batch_size).migrate()
  File "/usr/src/v6_api/c2corg_api/scripts/migration/users.py", line 70, in migrate
    email_validated=id not in pending
  File "/usr/src/v6_api/c2corg_api/scripts/migration/batch.py", line 52, in add
    self.flush_or_not()
  File "/usr/src/v6_api/c2corg_api/scripts/migration/batch.py", line 14, in flush_or_not
    self.flush()
  File "/usr/src/v6_api/c2corg_api/scripts/migration/batch.py", line 59, in flush
    self.session.bulk_insert_mappings(self.model, self.entities)
  File "/usr/src/v6_api/.build/venv/local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 2280, in bulk_insert_mappings
    mapper, mappings, False, False, return_defaults, False)
  File "/usr/src/v6_api/.build/venv/local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 2351, in _bulk_save_mappings
    transaction.rollback(_capture_exception=True)
  File "/usr/src/v6_api/.build/venv/local/lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py", line 60, in __exit__
    compat.reraise(exc_type, exc_value, exc_tb)
  File "/usr/src/v6_api/.build/venv/local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 2346, in _bulk_save_mappings
    mapper, mappings, transaction, isstates, return_defaults)
  File "/usr/src/v6_api/.build/venv/local/lib/python2.7/site-packages/sqlalchemy/orm/persistence.py", line 67, in _bulk_insert
    bookkeeping=return_defaults)
  File "/usr/src/v6_api/.build/venv/local/lib/python2.7/site-packages/sqlalchemy/orm/persistence.py", line 752, in _emit_insert_statements
    execute(statement, multiparams)
  File "/usr/src/v6_api/.build/venv/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 914, in execute
    return meth(self, multiparams, params)
  File "/usr/src/v6_api/.build/venv/local/lib/python2.7/site-packages/sqlalchemy/sql/elements.py", line 323, in _execute_on_connection
    return connection._execute_clauseelement(self, multiparams, params)
  File "/usr/src/v6_api/.build/venv/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1010, in _execute_clauseelement
    compiled_sql, distilled_params
  File "/usr/src/v6_api/.build/venv/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1146, in _execute_context
    context)
  File "/usr/src/v6_api/.build/venv/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1341, in _handle_dbapi_exception
    exc_info
  File "/usr/src/v6_api/.build/venv/local/lib/python2.7/site-packages/sqlalchemy/util/compat.py", line 199, in raise_from_cause
    reraise(type(exception), exception, tb=exc_tb)
  File "/usr/src/v6_api/.build/venv/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1116, in _execute_context
    context)
  File "/usr/src/v6_api/.build/venv/local/lib/python2.7/site-packages/sqlalchemy/engine/default.py", line 447, in do_executemany
    cursor.executemany(statement, parameters)
sqlalchemy.exc.IntegrityError: (psycopg2.IntegrityError) duplicate key value violates unique constraint "user_email_key"
DETAIL:  Key (email)=(<redacted>) already exists.

ORM query object from REST url for filter

The API will have to handle the transformation of REST urls like
http://www.camptocamp.org/outings/list/summits/639674-41487-40127/orderby/act/order/asc to
SQLAlchemy Query objects.
In v5, this is done by parsing the URL and delagating to a collection of helper functions like found at https://github.com/c2corg/camptocamp.org/blob/master/lib/model/doctrine/generated/BaseDocument.class.php#L214.
I have not found ready to use libraries for handling this.

User profile

TODO:

  • prevent indexing in Elastic search of content/summary for privacy.

Locales in listings?

When requesting a single document in a specific culture, you will get the document only with that culture or 404 if there is no translation of the document for the culture.

But how should we do it for listings? Currently all locales are returned for the documents. But is that necessary? Should we maybe only return a preferred locale for each document? And if the preferred locale is not available use a different locale?

Handling of 500 errors

(Just a question, perhaps the current behaviour is OK)

When making AJAX requests to the API from the UI, if the API crashed because of some error (eg. missing field in DB), Angular's $http actually returns an object with "status: 500" (which is correct) and a data properties containing an HTML output with the 500 error returned by the API.
Should we do something in order to get a cleaner JSON output instead of the raw pyramid 500 page?

Sequence problem with documents_locales.document_id?

Not sure if this is a significant problem but I read in the logs that:

[Wed Nov 04 20:58:07.934469 2015] [wsgi:error] [pid 30447] /var/www/vhosts/c2cassoc_c2corgv6/private/v6_api/.build/venv/lib/python2.7/site-packages/sqlalchemy/sql/default_comparator.py:153: SAWarning: The IN-predicate on "documents_locales.document_id" was invoked with an empty sequence. This results in a contradiction, which nonetheless can be expensive to evaluate. Consider alternative strategies for improved performance.

It seems not systematic, but showed from time to time (when trying to display a document on the main dev instance).

Returning a document for a single culture

When displaying a document, in most cases it is no use retrieving all cultures, since only one is displayed.

As for now the API returns all available cultures for a given document call.
It would be useful to be able to specify the desired culture.

Fine tune CORS policies depending on the READ/WRITE actions

See #48 (comment) from @gberaudo

We discussed with @asaunier and it appears we should have two policies:

  • one for public data, restricted to GET method and allowed for *;
  • the other for the rest (restricted data), only allowed for c2corg and requiring credentials (JWT).

"cors_policy" in https://github.com/c2corg/v6_api/blob/master/c2corg_api/views/__init__.py#L15 should be renamed to "cors_public_policy" and, according to @gberaudo

The policy should be passed to each view (GET and PUT should be handled differently).
We could use annotations like: @public_json_view and @restricted_json_view instead of @json_view.

backref versus back_populates

We currently use a backref in the document relationship set on DocumentVersion. That backref creates a (view-only) relationship versions on Document, which makes sense.

At pyconfr I attended an SQLAlchemy talk where the presenter recommended to use back_populates instead of backref.

back_populates has the same meaning as backref, except that the complementing relationship property is not created automatically. So using back_populates makes the model code more explicit, with no hidden/implicit properties.

See the relationship-backref documentation for more information.

This is a minor thing, but I thought I could mention it here :)

Authorization checks fail in the API demo instance

Actions requiring authorization fail in the API demo instance (OK on dev instances) despite the token is actually provided in the Authorization header and available in the token table.

For instance:

  • logging out:
403 Forbidden
Access was denied to this resource.
Unauthorized: UserLogoutRest.post__POST failed permission check
  • creating a WP:
403 Forbidden
  Access was denied to this resource.
debug_authorization of url http://<...>/api/waypoints (view name u'' against context &lt;c2corg_api.RootFactory object at 0x7f3bdc5de350&gt;): ACLDenied permission 'authenticated' via ACE '&lt;default deny&gt;' in ACL [('Allow', 'system.Everyone', 'public'), ('Allow', 'system.Authenticated', 'authenticated'), ('Allow', 'group:moderators', 'moderator')] on context &lt;c2corg_api.RootFactory object at 0x7f3bdc5de350&gt; for principals ['system.Everyone']

Geo-associations

I paste here info sent by email to @tsauerwein a few days ago.

Geoassociations are associations between usual documents (WP, routes, outings, images, etc.) with region documents (http://www.camptocamp.org/areas => countries, CH cantons / F departements and ranges/massifs) and in some cases "paper maps" (http://www.camptocamp.org/maps)

  • It's not worth spending too much time about maps. In v5 it's a kind of document but it's not that important. I don't think they are often used. The goal was to automatically list the maps without having to type the map names in a text field, at least in France and Switzerland where we had the geometries.
    Not sure we even need to have a "map" document type in v6: if we can provide the list of maps (even without linking toward a detail page for the map) intersecting the current page geometry I guess it's enough.
    Please note that we don't show linked maps in a document lists => the associations could be computed on the fly when showing a document if it has at least a default geometry.
  • regions are more important since they can be used to filter documents (eg. "show me outings in Mont-Blanc range"). Regions associations may be needed in many pages (detail page, list page) for almost all doc types.
    In v5 even books may be linked to regions (based upon linked routes)! For instance: http://www.camptocamp.org/books/704165/fr/scialpinismo-in-svizzera
    To be honest, I wonder if it is really needed. Of course it's useful to get the list of guidebooks for a given region. But you don't do that kind of search very often.

It is worth figuring out if we stick to table-based geo associations (as in v5) or if we can use geographical operations by having a associated-docs-based default geometry when the document has no own geometry. The latter solution would be more flexible I think and would allow to make proximity searching or box/polygon filtering for all documents. It would also be needed (required?) for map-extent based filtering in search pages (see wireframes about "topoguide"/"page de recherche").

I wonder if we would not need a "point" default geometry for all documents, including the routes and outings. It would be useful for instance to:

  • make map filtering (advanced search)
  • show outings on the map: even if we have line geometries, it is probably more usable/performant to show markers rather than a bunch of lines? especially if all features have no own geometry. That probaby can be challenged since in some cases (routes in a WP page for instance) it's interesting to show the actual lines.
  • make region filtering (not only a map extent filtering) => I guess it's more performant to get a list of points rather than lines when intersectiong with a polygons or even bboxes. Do you think we could replace the current v5 geo-associations filtering by point-geom-based intersections? Would it be too performances-hurting?

TypeError: to_archive() takes exactly 2 arguments (1 given)

When trying to update a waypoint in the UI, the API fails with the following error:

File "/home/alex/v6_api/c2corg_api/views/waypoint.py", line 57, in put
return self._put(Waypoint, schema_waypoint)
File "/home/alex/v6_api/c2corg_api/views/document.py", line 86, in _put
changed_langs)
File "/home/alex/v6_api/c2corg_api/views/document.py", line 154, in _update_version
locale_archive = self._get_locale_archive(locale, changed_langs)
File "/home/alex/v6_api/c2corg_api/views/document.py", line 215, in _get_locale_archive
locale_archive = locale.to_archive()
TypeError: to_archive() takes exactly 2 arguments (1 given)

Line 215 is

        if locale.culture in changed_langs:
            # create new archive version for this locale
            locale_archive = locale.to_archive()

https://github.com/c2corg/v6_api/blob/master/c2corg_api/views/document.py#L213-L215
whereas DocumentLocale.to_locale() indeed requires a "locale" argument:

    def to_archive(self, locale):
        copy_attributes(self, locale, DocumentLocale._ATTRIBUTES)
        return locale

https://github.com/c2corg/v6_api/blob/master/c2corg_api/models/document.py#L236-L238

Special case of route names

Route names are a special case compared to other documents titles because they are closely related to the associated waypoints.

For instance http://www.camptocamp.org/routes/53781/fr/mont-blanc-arete-des-bosses

  • displayed route name is "Mont Blanc : Arête des Bosses".
  • the actual route name is "Arête des Bosses" though. The summit name is appended first in order to "discriminize" the route name, for instance when the route name itself is too common (eg. "Face N").

Several drawbacks with this approach:

  • In v5 the displayed route name determination is really (too!) complicated: when several summits are associated to the route, the highest summit is used (based upon the summit elevation attribute). Then if the summit has several culture, the most appropriate one must be figured out depending on the interface language or user's preferences. This is done every time the route name must be displayed (even though some caching may be used in some cases).
  • In the mapfile it is not possible to make that complicated computations and the route names displayed for vector features on the maps omit the summit name.
  • In some cases, the highest summit is not the most relevent one (eg. a route to a hut that would go through some pass above the hut).
  • In some cases omitting the summit name would make sense, eg. for raids.

With @tsauerwein we considered moving the summit name (if relevent) directly into the route title field. I have discussed it with the association and it would cause other problems. For instance when climbing sites are reorganised, if a bunch of routes are transfered from one site to another, one would have to change all the route names by hand. Ditto if a new culture is added to the summit with a different summit name (eg. Cervin/Cervino/Matterhorn). In addition contributors would most likely introduce inconsistencies in route names, for instance "Cervin : Face N", "Cervin Face N", "Cervin / Face N", "Face N du Cervin" or even "Face N" (summit name incorrectly omitted).

By the way having the summit name in the route name attribute would require to adapt the v5>v6 migration script.

Please note that in v6 using WP names (not only summit names) would make sense. For instance for hut-access routes, climbing route names including the name of a climbing site.

Suggested solution (to be precised and debated in the current issue):

  • the route title attribute still contains only the actual route name (no WP name is embedded). As in v5.
  • The displayed route name contains a WP name as well. As in v5. Except maybe for some route types (eg. raids).
  • in the route detail page, it should be possible to specify the "main WP" among associated WPs. If only one WP, it is automatically considered as the main WP. If several WP are associated, the main WP would be the highest one by default.
  • In order to avoid complicated computations when displaying the route name (including for instance in the mapfile), the routes "locale" (i18n) table [1] would contain a "prefix" attribute that would automatically be set with the "main WP" title. This attribute would be updated whenever the "main WP" is changed or renamed. We could also have a "waypoint_id" attribute in the route table if it helps figuring out the routes that must be updated when a waypoint changes.
  • Since the prefix is not really related to the route data itself, it is not necessary to create a new entry in the route archives when the "main WP" is changed or renamed (ie. when the "prefix" attribute must be updated) => the "prefix" attribute would be available only in table "routes_locales" not in table "routes_locales_archives". Which means that when a new version of the route is created, the "prefix" attribute should be preserved.

Please note that the route indexing in Elastic Search is also impacted by the current issue: the route index should take into account the names of all WP associated to a given route, so that the route is returned when searching on a WP name.

[1] https://github.com/c2corg/v6_api/blob/master/c2corg_api/models/route.py#L228

TODO: indexing WP names when indexing routes

Login errors on the main dev instance

Logging in with an existing account (for instance "alex/c2c") fails with the following server error:

[Wed Dec 09 16:19:01.060912 2015] [wsgi:error] [pid 23485] [remote 10.27.71.4:5099]   File "/var/www/vhosts/c2cassoc_c2corgv6/private/v6_api/c2corg_api/views/user.py", line 127, in post
[Wed Dec 09 16:19:01.060973 2015] [wsgi:error] [pid 23485] [remote 10.27.71.4:5099]     token = try_login(user, password, request) if user else None
[Wed Dec 09 16:19:01.061123 2015] [wsgi:error] [pid 23485] [remote 10.27.71.4:5099]   File "/var/www/vhosts/c2cassoc_c2corgv6/private/v6_api/c2corg_api/security/roles.py", line 68, in try_login
[Wed Dec 09 16:19:01.061209 2015] [wsgi:error] [pid 23485] [remote 10.27.71.4:5099]     if user.validate_password(password, DBSession):
[Wed Dec 09 16:19:01.061246 2015] [wsgi:error] [pid 23485] [remote 10.27.71.4:5099]   File "/var/www/vhosts/c2cassoc_c2corgv6/private/v6_api/c2corg_api/models/user.py", line 69, in validate_password
[Wed Dec 09 16:19:01.061317 2015] [wsgi:error] [pid 23485] [remote 10.27.71.4:5099]     if PasswordUtil.is_password_valid(plain_password, self._password):
[Wed Dec 09 16:19:01.061347 2015] [wsgi:error] [pid 23485] [remote 10.27.71.4:5099]   File "/var/www/vhosts/c2cassoc_c2corgv6/private/v6_api/c2corg_api/models/user.py", line 29, in is_password_valid
[Wed Dec 09 16:19:01.061377 2015] [wsgi:error] [pid 23485] [remote 10.27.71.4:5099]     return bcrypt.hashpw(plain, encrypted) == encrypted
[Wed Dec 09 16:19:01.061411 2015] [wsgi:error] [pid 23485] [remote 10.27.71.4:5099]   File "/var/www/vhosts/c2cassoc_c2corgv6/private/v6_api/.build/venv/lib/python2.7/site-packages/bcrypt/__init__.py", line 66, in hashpw
[Wed Dec 09 16:19:01.061460 2015] [wsgi:error] [pid 23485] [remote 10.27.71.4:5099]     raise ValueError("Invalid salt")
[Wed Dec 09 16:19:01.061575 2015] [wsgi:error] [pid 23485] [remote 10.27.71.4:5099] ValueError: Invalid salt

If I create a new account ("c2calex/toto"), the login fails with another error:

[Wed Dec 09 16:21:12.849428 2015] [wsgi:error] [pid 23485] [remote 10.27.71.4:64008]   File "/var/www/vhosts/c2cassoc_c2corgv6/private/v6_api/c2corg_api/views/user.py", line 127, in post
[Wed Dec 09 16:21:12.849512 2015] [wsgi:error] [pid 23485] [remote 10.27.71.4:64008]     token = try_login(user, password, request) if user else None
[Wed Dec 09 16:21:12.849574 2015] [wsgi:error] [pid 23485] [remote 10.27.71.4:64008]   File "/var/www/vhosts/c2cassoc_c2corgv6/private/v6_api/c2corg_api/security/roles.py", line 73, in try_login
[Wed Dec 09 16:21:12.849705 2015] [wsgi:error] [pid 23485] [remote 10.27.71.4:64008]     token = policy.encode_jwt(request, claims=claims)
[Wed Dec 09 16:21:12.849782 2015] [wsgi:error] [pid 23485] [remote 10.27.71.4:64008]   File "/var/www/vhosts/c2cassoc_c2corgv6/private/v6_api/.build/venv/lib/python2.7/site-packages/pyramid_jwtauth/__init__.py", line 359, in encode_jwt
[Wed Dec 09 16:21:12.849881 2015] [wsgi:error] [pid 23485] [remote 10.27.71.4:64008]     jwtauth_token = jwt.encode(encode_claims, key=key, algorithm=algorithm)
[Wed Dec 09 16:21:12.849943 2015] [wsgi:error] [pid 23485] [remote 10.27.71.4:64008]   File "/var/www/vhosts/c2cassoc_c2corgv6/private/v6_api/.build/venv/lib/python2.7/site-packages/jwt/api_jwt.py", line 56, in encode
[Wed Dec 09 16:21:12.868320 2015] [wsgi:error] [pid 23485] [remote 10.27.71.4:64008]     json_payload, key, algorithm, headers, json_encoder
[Wed Dec 09 16:21:12.868527 2015] [wsgi:error] [pid 23485] [remote 10.27.71.4:64008]   File "/var/www/vhosts/c2cassoc_c2corgv6/private/v6_api/.build/venv/lib/python2.7/site-packages/jwt/api_jws.py", line 97, in encode
[Wed Dec 09 16:21:12.872449 2015] [wsgi:error] [pid 23485] [remote 10.27.71.4:64008]     key = alg_obj.prepare_key(key)
[Wed Dec 09 16:21:12.872591 2015] [wsgi:error] [pid 23485] [remote 10.27.71.4:64008]   File "/var/www/vhosts/c2cassoc_c2corgv6/private/v6_api/.build/venv/lib/python2.7/site-packages/jwt/algorithms.py", line 116, in prepare_key
[Wed Dec 09 16:21:12.877363 2015] [wsgi:error] [pid 23485] [remote 10.27.71.4:64008]     raise TypeError('Expecting a string- or bytes-formatted key.')
[Wed Dec 09 16:21:12.877520 2015] [wsgi:error] [pid 23485] [remote 10.27.71.4:64008] TypeError: Expecting a string- or bytes-formatted key.

I also had to set export cors_origins = * in config/main else login/register requests are rejected.

@gberaudo please help! :P

Auth TODO

  • add user table and methods;
  • add stubbed user creation methods;
  • add constraint on user on history_metadata (set user when creating a document version)
  • set user in migration script
  • store and retrieve and delete active tokens from database;
  • add token refresh method;
  • add or modify unit tests to check methods permissions;
  • read and write cookies? (see https://github.com/c2corg/v6_api/wiki/Authentication-Concept)
  • check password migration from v5, notably unicode passwords
  • add index to the token table on the value
  • discourse integration
  • clean expired tokens from database (see bbdef2a)

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.