2017-07-16 17:14:21 +02:00
package apiController
2017-05-05 16:39:15 +02:00
2017-05-08 11:18:49 +02:00
import (
2017-05-05 16:39:15 +02:00
"html"
2017-05-08 11:18:49 +02:00
"net/http"
2017-05-05 16:39:15 +02:00
"strconv"
2017-05-11 05:04:11 +02:00
"strings"
2017-05-08 11:18:49 +02:00
"time"
2017-05-17 07:58:40 +02:00
"github.com/NyaaPantsu/nyaa/config"
2017-07-16 17:14:21 +02:00
"github.com/NyaaPantsu/nyaa/controllers/feed"
2017-07-20 20:21:57 +02:00
"github.com/NyaaPantsu/nyaa/controllers/router"
2017-06-29 13:15:23 +02:00
"github.com/NyaaPantsu/nyaa/models"
"github.com/NyaaPantsu/nyaa/models/torrents"
2017-07-02 18:00:12 +02:00
"github.com/NyaaPantsu/nyaa/models/users"
2017-08-01 14:47:27 +02:00
"github.com/NyaaPantsu/nyaa/utils/api"
2017-07-02 16:54:55 +02:00
"github.com/NyaaPantsu/nyaa/utils/cookies"
"github.com/NyaaPantsu/nyaa/utils/crypto"
"github.com/NyaaPantsu/nyaa/utils/log"
msg "github.com/NyaaPantsu/nyaa/utils/messages"
"github.com/NyaaPantsu/nyaa/utils/search"
"github.com/NyaaPantsu/nyaa/utils/upload"
2017-07-02 18:00:12 +02:00
"github.com/NyaaPantsu/nyaa/utils/validator"
"github.com/NyaaPantsu/nyaa/utils/validator/torrent"
"github.com/NyaaPantsu/nyaa/utils/validator/user"
2017-06-28 13:42:38 +02:00
"github.com/gin-gonic/gin"
2017-07-28 05:46:40 +02:00
"github.com/ory/fosite"
"github.com/pkg/errors"
2017-05-05 16:39:15 +02:00
)
2017-07-09 14:53:52 +02:00
/ * *
* @ apiDefine NotFoundError
2017-07-22 17:21:14 +02:00
* @ apiVersion 1.1 .1
2017-07-09 14:53:52 +02:00
* @ apiError { String [ ] } errors List of errors messages with a 404 error message in it .
*
* @ apiErrorExample Error - Response :
* HTTP / 1.1 404 Not Found
* {
* "errors" : [ "404_not_found" , ... ]
* }
* /
/ * *
* @ apiDefine RequestError
2017-07-22 17:21:14 +02:00
* @ apiVersion 1.1 .1
2017-07-09 14:53:52 +02:00
* @ apiError { Boolean } ok The request couldn ' t be done due to some errors .
* @ apiError { String [ ] } errors List of errors messages .
* @ apiError { Object [ ] } all_errors List of errors object messages for each wrong field
*
* @ apiErrorExample Error - Response :
* HTTP / 1.1 200 OK
* {
* "ok" : false ,
* "errors" : [ ... ]
* "all_errors" : {
* "username" : [ ... ] ,
* }
* }
* /
/ * *
* @ api { get } / Request Torrents index
2017-07-22 17:21:14 +02:00
* @ apiVersion 1.1 .1
2017-07-09 14:53:52 +02:00
* @ apiName GetTorrents
* @ apiGroup Torrents
*
* @ apiParam { Number } id Torrent unique ID .
*
* @ apiSuccess { Object [ ] } torrents List of torrent object ( see view for the properties ) .
* @ apiSuccess { Number } queryRecordCount Number of torrents given .
* @ apiSuccess { Number } totalRecordCount Total number of torrents .
*
* @ apiSuccessExample Success - Response :
* HTTP / 1.1 200 OK
* {
* "torrents" : [ ... ] ,
* "queryRecordCount" : 50 ,
* "totalRecordCount" : 798414
* }
*
* @ apiUse NotFoundError
* /
2017-05-25 21:54:58 +02:00
// APIHandler : Controller for api request on torrent list
2017-06-28 13:42:38 +02:00
func APIHandler ( c * gin . Context ) {
2017-07-09 14:53:52 +02:00
c . Header ( "Content-Type" , "application/json" )
2017-06-28 13:42:38 +02:00
t := c . Query ( "t" )
2017-06-16 01:30:09 +02:00
if t != "" {
2017-07-16 17:14:21 +02:00
feedController . RSSTorznabHandler ( c )
2017-06-16 01:30:09 +02:00
} else {
2017-07-20 20:21:57 +02:00
APISearchHandler ( c )
2017-05-05 16:39:15 +02:00
}
}
2017-07-09 14:53:52 +02:00
/ * *
* @ api { get } / view / : id Request Torrent information
2017-07-22 17:21:14 +02:00
* @ apiVersion 1.1 .1
2017-07-09 14:53:52 +02:00
* @ apiName GetTorrent
* @ apiGroup Torrents
*
* @ apiParam { Number } id Torrent unique ID .
*
* @ apiSuccess { Number } id ID of the torrent .
* @ apiSuccess { String } name Name of the torrent .
* @ apiSuccess { Number } status Status of the torrent .
* @ apiSuccess { String } hash Hash of the torrent .
* @ apiSuccess { Date } date Uploaded date of the torrent .
* @ apiSuccess { Number } filesize File size in Bytes of the torrent .
* @ apiSuccess { String } description Description of the torrent .
* @ apiSuccess { Object [ ] } comments Comments of the torrent .
* @ apiSuccess { String } sub_category Sub Category of the torrent .
* @ apiSuccess { String } category Category of the torrent .
* @ apiSuccess { String } anidb_id Anidb ID of the torrent .
* @ apiSuccess { Number } uploader_id ID of the torrent uploader .
* @ apiSuccess { String } uploader_name Username of the torrent uploader .
* @ apiSuccess { String } uploader_old Old username from nyaa of the torrent uploader .
* @ apiSuccess { String } website_link External Link of the torrent .
* @ apiSuccess { String [ ] } languages Languages of the torrent .
* @ apiSuccess { String } magnet Magnet URI of the torrent .
* @ apiSuccess { String } torrent Download URL of the torrent .
* @ apiSuccess { Number } seeders Number of seeders of the torrent .
* @ apiSuccess { Number } leechers Number of leechers of the torrent .
* @ apiSuccess { Number } completed Downloads completed of the torrent .
* @ apiSuccess { Date } last_scrape Last statistics update of the torrent .
* @ apiSuccess { Object [ ] } file_list List of files in the torrent .
*
* @ apiSuccessExample Success - Response :
* HTTP / 1.1 200 OK
* {
* "id" : 952801 ,
* "name" : "[HorribleSubs] Uchouten Kazoku S2 [720p]" ,
* "status" : 1 ,
* "hash" : "6E4D96F7A0B0456672E80B150CCB7C15868CD47D" ,
* "date" : "2017-07-05T11:01:39Z" ,
* "filesize" : 4056160259 ,
* "description" : "<p>Unofficial batch</p>\n" ,
* "comments" : [ ] ,
* "sub_category" : "5" ,
* "category" : "3" ,
* "anidb_id" : "" ,
* "downloads" : 0 ,
* "uploader_id" : 7177 ,
* "uploader_name" : "DarAR92" ,
* "uploader_old" : "" ,
* "website_link" : "http://horriblesubs.info/" ,
* "languages" : [
* "en-us"
* ] ,
* "magnet" : "magnet:?xt=urn:btih:6E4D96F7A0B0456672E80B150CCB7C15868CD47D&dn=%5BHorribleSubs%5D+Uchouten+Kazoku+S2+%5B720p%5D&tr=http://nyaa.tracker.wf:7777/announce&tr=http://nyaa.tracker.wf:7777/announce&tr=udp://tracker.doko.moe:6969&tr=http://tracker.anirena.com:80/announce&tr=http://anidex.moe:6969/announce&tr=udp://tracker.opentrackr.org:1337&tr=udp://tracker.coppersurfer.tk:6969&tr=udp://tracker.leechers-paradise.org:6969&tr=udp://zer0day.ch:1337&tr=udp://9.rarbg.com:2710/announce&tr=udp://tracker2.christianbro.pw:6969/announce&tr=udp://tracker.coppersurfer.tk:6969&tr=udp://tracker.leechers-paradise.org:6969&tr=udp://eddie4.nl:6969/announce&tr=udp://tracker.doko.moe:6969/announce" ,
* "torrent" : "https://nyaa.pantsu.cat/download/6E4D96F7A0B0456672E80B150CCB7C15868CD47D" ,
* "seeders" : 4 ,
* "leechers" : 2 ,
* "completed" : 28 ,
* "last_scrape" : "2017-07-07T07:48:32.509635Z" ,
* "file_list" : [
* {
* "path" : "[HorribleSubs] Uchouten Kazoku S2 - 01[720p].mkv" ,
* "filesize" : 338250895
* } ,
* {
* "path" : "[HorribleSubs] Uchouten Kazoku S2 - 12 [720p].mkv" ,
* "filesize" : 338556275
* }
* ]
* }
*
* @ apiUse NotFoundError
* /
2017-05-25 21:54:58 +02:00
// APIViewHandler : Controller for viewing a torrent by its ID
2017-06-28 13:42:38 +02:00
func APIViewHandler ( c * gin . Context ) {
2017-07-09 14:53:52 +02:00
c . Header ( "Content-Type" , "application/json" )
2017-07-02 18:00:12 +02:00
id , _ := strconv . ParseInt ( c . Param ( "id" ) , 10 , 32 )
2017-05-05 16:39:15 +02:00
2017-07-02 18:00:12 +02:00
torrent , err := torrents . FindByID ( uint ( id ) )
2017-05-23 05:18:25 +02:00
if err != nil {
2017-06-28 13:42:38 +02:00
c . AbortWithError ( http . StatusNotFound , err )
2017-05-23 05:18:25 +02:00
return
}
Consistency, formatting, error checking, cleanup, and a couple bug fixes (#245)
* Checkpoint: it builds
The config, db, model, network, os, and public packages have had some
fixes to glaringly obvious flaws, dead code removed, and stylistic
changes.
* Style changes and old code removal in router
Router needs a lot of work done to its (lack of) error handling.
* Dead code removal and style changes
Now up to util/email/email.go. After I'm finished with the initial sweep
I'll go back and fix error handling and security issues. Then I'll fix
the broken API. Then I'll go through to add documentation and fix code
visibility.
* Finish dead code removal and style changes
Vendored libraries not touched. Everything still needs security fixes
and documentation. There's also one case of broken functionality.
* Fix accidental find-and-replace
* Style, error checking, saftey, bug fix changes
* Redo error checking erased during merge
* Re-add merge-erased fix. Make Safe safe.
2017-05-10 04:34:40 +02:00
b := torrent . ToJSON ( )
2017-06-28 13:42:38 +02:00
c . JSON ( http . StatusOK , b )
2017-05-06 23:46:53 +02:00
}
2017-05-08 11:18:49 +02:00
2017-07-09 14:53:52 +02:00
/ * *
* @ api { get } / head / : id Request Torrent Head
2017-07-22 17:21:14 +02:00
* @ apiVersion 1.1 .1
2017-07-09 14:53:52 +02:00
* @ apiName GetTorrentHead
* @ apiGroup Torrents
*
* @ apiParam { Number } id Torrent unique ID .
*
* @ apiSuccessExample Success - Response :
* HTTP / 1.1 200 OK
*
* @ apiUse NotFoundError
* /
2017-05-25 21:54:58 +02:00
// APIViewHeadHandler : Controller for checking a torrent by its ID
2017-06-28 13:42:38 +02:00
func APIViewHeadHandler ( c * gin . Context ) {
2017-07-09 14:53:52 +02:00
c . Header ( "Content-Type" , "application/json" )
2017-06-28 13:42:38 +02:00
id , err := strconv . ParseInt ( c . Param ( "id" ) , 10 , 32 )
2017-05-23 05:18:19 +02:00
if err != nil {
return
}
2017-07-02 18:00:12 +02:00
_ , err = torrents . FindRawByID ( uint ( id ) )
2017-05-23 05:18:19 +02:00
if err != nil {
2017-07-09 14:53:52 +02:00
c . AbortWithError ( http . StatusNotFound , err )
2017-05-23 05:18:19 +02:00
return
}
2017-06-28 13:42:38 +02:00
c . Writer . Write ( nil )
2017-05-23 05:18:19 +02:00
}
2017-07-09 14:53:52 +02:00
/ * *
* @ api { post } / upload Upload a Torrent
2017-07-22 17:21:14 +02:00
* @ apiVersion 1.1 .1
2017-07-09 14:53:52 +02:00
* @ apiName UploadTorrent
* @ apiGroup Torrents
*
* @ apiParam { String } username Torrent uploader name .
* @ apiParam { String } name Torrent name .
* @ apiParam { String } magnet Torrent magnet URI .
* @ apiParam { String } category Torrent category .
* @ apiParam { Boolean } remake Torrent is a remake .
* @ apiParam { String } description Torrent description .
* @ apiParam { Number } status Torrent status .
* @ apiParam { Boolean } hidden Torrent hidden .
* @ apiParam { String } website_link Torrent website link .
* @ apiParam { String [ ] } languages Torrent languages .
* @ apiParam { File } torrent Torrent file to upload ( you have to send a torrent file or a magnet , not both ! ) .
*
* @ apiSuccess { Boolean } ok The request is done without failing
* @ apiSuccess { String [ ] } infos Messages information relative to the request
* @ apiSuccess { Object } data The resulting torrent uploaded ( see view for the properties )
*
* @ apiSuccessExample Success - Response :
* HTTP / 1.1 200 OK
*
* @ apiUse RequestError
* /
2017-05-25 21:54:58 +02:00
// APIUploadHandler : Controller for uploading a torrent with api
2017-06-28 13:42:38 +02:00
func APIUploadHandler ( c * gin . Context ) {
2017-07-09 14:53:52 +02:00
c . Header ( "Content-Type" , "application/json" )
2017-06-28 13:42:38 +02:00
token := c . Request . Header . Get ( "Authorization" )
username := c . PostForm ( "username" )
2017-07-02 18:00:12 +02:00
user , _ , _ , _ , err := users . FindByAPITokenAndName ( token , username )
2017-06-28 13:42:38 +02:00
messages := msg . GetMessages ( c )
2017-05-20 01:10:16 +02:00
2017-06-05 15:19:25 +02:00
if err != nil {
2017-06-28 13:42:38 +02:00
messages . AddErrorT ( "errors" , "error_api_token" )
2017-06-05 15:19:25 +02:00
}
2017-07-02 18:00:12 +02:00
if ! user . CanUpload ( ) {
2017-06-28 13:42:38 +02:00
messages . AddErrorT ( "errors" , "uploads_disabled" )
2017-05-08 11:18:49 +02:00
}
2017-05-20 01:10:16 +02:00
2017-05-11 05:04:11 +02:00
if user . ID == 0 {
2017-07-02 18:00:12 +02:00
messages . AddErrorT ( "errors" , "error_api_token" )
2017-06-05 15:19:25 +02:00
}
2017-05-28 06:22:39 +02:00
2017-06-13 08:01:57 +02:00
if ! messages . HasErrors ( ) {
2017-07-02 23:53:23 +02:00
uploadForm := upload . NewTorrentRequest ( )
2017-06-28 13:42:38 +02:00
contentType := c . Request . Header . Get ( "Content-Type" )
if contentType != "application/json" && ! strings . HasPrefix ( contentType , "multipart/form-data" ) && contentType != "application/x-www-form-urlencoded" {
2017-07-02 18:00:12 +02:00
// TODO What should we do here ? uploadForm is empty so we shouldn't
2017-06-13 08:01:57 +02:00
// create a torrent from it
2017-06-28 13:42:38 +02:00
messages . AddErrorT ( "errors" , "error_content_type_post" )
2017-06-13 08:01:57 +02:00
}
// As long as the right content-type is sent, formValue is smart enough to parse it
2017-07-02 23:53:23 +02:00
err = upload . ExtractInfo ( c , uploadForm )
2017-06-13 08:01:57 +02:00
if err != nil {
2017-06-28 13:42:38 +02:00
messages . Error ( err )
2017-06-05 15:19:25 +02:00
}
2017-05-26 01:48:14 +02:00
2017-06-13 08:01:57 +02:00
if ! messages . HasErrors ( ) {
2017-07-02 18:00:12 +02:00
uploadForm . Status = models . TorrentStatusNormal
if uploadForm . Remake { // overrides trusted
uploadForm . Status = models . TorrentStatusRemake
2017-06-13 08:01:57 +02:00
} else if user . IsTrusted ( ) {
2017-07-02 18:00:12 +02:00
uploadForm . Status = models . TorrentStatusTrusted
2017-06-13 08:01:57 +02:00
}
2017-07-02 18:00:12 +02:00
err = torrents . ExistOrDelete ( uploadForm . Infohash , user )
2017-06-05 15:19:25 +02:00
if err != nil {
2017-06-28 13:42:38 +02:00
messages . Error ( err )
2017-06-13 08:01:57 +02:00
}
if ! messages . HasErrors ( ) {
2017-07-02 23:53:23 +02:00
torrent , err := torrents . Create ( user , uploadForm )
2017-07-02 18:00:12 +02:00
if err != nil {
messages . Error ( err )
2017-06-13 08:01:57 +02:00
}
messages . AddInfoT ( "infos" , "torrent_uploaded" )
2017-07-02 18:00:12 +02:00
2017-08-01 14:47:27 +02:00
apiUtils . ResponseHandler ( c , torrent . ToJSON ( ) )
2017-06-05 15:19:25 +02:00
return
2017-05-26 01:48:14 +02:00
}
}
2017-05-11 05:25:41 +02:00
}
2017-08-01 14:47:27 +02:00
apiUtils . ResponseHandler ( c )
2017-05-08 11:18:49 +02:00
}
2017-05-09 19:37:39 +02:00
2017-07-09 14:53:52 +02:00
/ * *
2017-10-18 06:02:37 +02:00
* @ api { put } / update / Update a Torrent
2017-07-22 17:21:14 +02:00
* @ apiVersion 1.1 .1
2017-07-09 14:53:52 +02:00
* @ apiName UpdateTorrent
* @ apiGroup Torrents
*
* @ apiParam { String } username Torrent uploader name .
* @ apiParam { Number } id Torrent ID .
* @ apiParam { String } name Torrent name .
* @ apiParam { String } category Torrent category .
* @ apiParam { Boolean } remake Torrent is a remake .
* @ apiParam { String } description Torrent description .
* @ apiParam { Number } status Torrent status .
* @ apiParam { Boolean } hidden Torrent hidden .
* @ apiParam { String } website_link Torrent website link .
* @ apiParam { String [ ] } languages Torrent languages .
*
* @ apiSuccess { Boolean } ok The request is done without failing
* @ apiSuccess { String [ ] } infos Messages information relative to the request
* @ apiSuccess { Object } data The resulting torrent updated ( see view for the properties )
*
* @ apiSuccessExample Success - Response :
* HTTP / 1.1 200 OK
*
* @ apiUse RequestError
* /
2017-05-25 21:54:58 +02:00
// APIUpdateHandler : Controller for updating a torrent with api
2017-06-28 13:42:38 +02:00
func APIUpdateHandler ( c * gin . Context ) {
2017-07-09 14:53:52 +02:00
c . Header ( "Content-Type" , "application/json" )
2017-06-28 13:42:38 +02:00
token := c . Request . Header . Get ( "Authorization" )
username := c . PostForm ( "username" )
2017-07-02 18:00:12 +02:00
user , _ , _ , _ , err := users . FindByAPITokenAndName ( token , username )
2017-06-28 13:42:38 +02:00
messages := msg . GetMessages ( c )
2017-05-20 01:10:16 +02:00
2017-06-05 15:19:25 +02:00
if err != nil {
2017-06-28 13:42:38 +02:00
messages . AddErrorT ( "errors" , "error_api_token" )
2017-06-05 15:19:25 +02:00
}
2017-07-02 18:00:12 +02:00
if ! user . CanUpload ( ) {
2017-06-28 13:42:38 +02:00
messages . AddErrorT ( "errors" , "uploads_disabled" )
2017-05-09 20:54:50 +02:00
}
2017-06-05 15:19:25 +02:00
if user . ID == 0 {
2017-07-02 18:00:12 +02:00
messages . AddErrorT ( "errors" , "error_api_token" )
2017-06-05 15:19:25 +02:00
}
2017-06-28 13:42:38 +02:00
contentType := c . Request . Header . Get ( "Content-Type" )
if contentType != "application/json" && ! strings . HasPrefix ( contentType , "multipart/form-data" ) && contentType != "application/x-www-form-urlencoded" {
2017-06-05 15:19:25 +02:00
// create a torrent from it
2017-06-28 13:42:38 +02:00
messages . AddErrorT ( "errors" , "error_content_type_post" )
2017-06-05 15:19:25 +02:00
}
2017-07-02 18:00:12 +02:00
update := torrentValidator . UpdateRequest { }
err = upload . ExtractEditInfo ( c , & update . Update )
2017-06-05 15:19:25 +02:00
if err != nil {
2017-06-28 13:42:38 +02:00
messages . Error ( err )
2017-06-05 15:19:25 +02:00
}
2017-06-13 08:01:57 +02:00
if ! messages . HasErrors ( ) {
2017-07-02 18:00:12 +02:00
c . Bind ( & update )
torrent , err := torrents . FindByID ( update . ID )
2017-08-01 23:38:13 +02:00
torrent . LoadTags ( )
2017-07-02 18:00:12 +02:00
if err != nil {
messages . AddErrorTf ( "errors" , "torrent_not_exist" , strconv . Itoa ( int ( update . ID ) ) )
2017-06-13 08:01:57 +02:00
}
if torrent . UploaderID != 0 && torrent . UploaderID != user . ID { //&& user.Status != mod
2017-07-02 18:00:12 +02:00
messages . AddErrorT ( "errors" , "fail_torrent_update" )
2017-06-13 08:01:57 +02:00
}
2017-07-05 17:06:24 +02:00
upload . UpdateTorrent ( & update , torrent , user ) . Update ( false )
2017-05-09 20:54:50 +02:00
}
2017-08-01 14:47:27 +02:00
apiUtils . ResponseHandler ( c )
2017-05-09 19:58:35 +02:00
}
2017-05-25 21:54:58 +02:00
2017-07-09 14:53:52 +02:00
/ * *
2017-07-20 20:55:28 +02:00
* @ api { get } / search / Search Torrents
2017-07-22 17:21:14 +02:00
* @ apiVersion 1.1 .1
2017-07-09 14:53:52 +02:00
* @ apiName FindTorrents
* @ apiGroup Torrents
*
* @ apiParam { String [ ] } c In which categories to search .
* @ apiParam { String } q Query to search ( torrent name ) .
2017-07-20 23:06:20 +02:00
* @ apiParam { Number } page Page of the search results .
2017-07-09 14:53:52 +02:00
* @ apiParam { String } limit Number of results per page .
* @ apiParam { String } userID Uploader ID owning the torrents .
* @ apiParam { String } fromID Show results with torrents ID superior to this .
* @ apiParam { String } s Torrent status .
* @ apiParam { String } maxage Torrents which have been uploaded the last x days .
* @ apiParam { String } toDate Torrents which have been uploaded since x < code > dateType < / code > .
* @ apiParam { String } fromDate Torrents which have been uploaded the last x < code > dateType < / code > .
* @ apiParam { String } dateType Which type of date ( < code > d < / code > for days , < code > m < / code > for months , < code > y < / code > for years ) .
* @ apiParam { String } minSize Filter by minimal size in < code > sizeType < / code > .
* @ apiParam { String } maxSize Filter by maximal size in < code > sizeType < / code > .
* @ apiParam { String } sizeType Which type of size ( < code > b < / code > for bytes , < code > k < / code > for kilobytes , < code > m < / code > for megabytes , < code > g < / code > for gigabytes ) .
* @ apiParam { String } sort Torrent sorting type ( 0 = id , 1 = name , 2 = date , 3 = downloads , 4 = size , 5 = seeders , 6 = leechers , 7 = completed ) .
* @ apiParam { Boolean } order Order ascending or descending ( true = ascending ) .
* @ apiParam { String [ ] } lang Filter the languages .
* @ apiParam { Number } page Search page .
*
* @ apiSuccess { Object [ ] } torrents List of torrent object ( see view for the properties ) .
*
* @ apiSuccessExample Success - Response :
* HTTP / 1.1 200 OK
* {
2017-07-20 20:21:57 +02:00
* "torrents" : [ ... ] ,
* "queryRecordCount" : 50 ,
* "totalRecordCount" : 798414
2017-07-09 14:53:52 +02:00
* }
*
* @ apiUse NotFoundError
* /
2017-05-25 21:54:58 +02:00
// APISearchHandler : Controller for searching with api
2017-06-28 13:42:38 +02:00
func APISearchHandler ( c * gin . Context ) {
2017-07-09 14:53:52 +02:00
c . Header ( "Content-Type" , "application/json" )
2017-07-20 23:06:20 +02:00
page := c . DefaultQuery ( "page" , c . Param ( "page" ) )
2017-07-20 20:21:57 +02:00
currentUser := router . GetUser ( c )
2017-05-25 02:42:35 +02:00
// db params url
var err error
pagenum := 1
if page != "" {
pagenum , err = strconv . Atoi ( html . EscapeString ( page ) )
if ! log . CheckError ( err ) {
2017-06-28 13:42:38 +02:00
c . AbortWithError ( http . StatusInternalServerError , err )
2017-05-25 02:42:35 +02:00
return
}
if pagenum <= 0 {
2017-07-16 17:14:21 +02:00
c . AbortWithStatus ( http . StatusNotFound )
2017-05-25 02:42:35 +02:00
return
}
}
2017-07-20 20:21:57 +02:00
userID , err := strconv . ParseUint ( c . Query ( "userID" ) , 10 , 32 )
if err != nil {
userID = 0
}
_ , torrentSearch , nbTorrents , err := search . AuthorizedQuery ( c , pagenum , currentUser . CurrentOrAdmin ( uint ( userID ) ) )
2017-05-25 02:42:35 +02:00
if err != nil {
2017-06-28 13:42:38 +02:00
c . AbortWithError ( http . StatusInternalServerError , err )
2017-05-25 02:42:35 +02:00
return
}
2017-07-20 20:21:57 +02:00
maxQuery , err := strconv . Atoi ( c . DefaultQuery ( "limit" , strconv . Itoa ( config . Get ( ) . Navigation . TorrentsPerPage ) ) )
if err != nil {
maxQuery = config . Get ( ) . Navigation . TorrentsPerPage
} else if maxQuery > config . Get ( ) . Navigation . MaxTorrentsPerPage {
maxQuery = config . Get ( ) . Navigation . MaxTorrentsPerPage
}
b := upload . APIResultJSON {
TotalRecordCount : nbTorrents ,
Torrents : torrents . APITorrentsToJSON ( torrentSearch ) ,
QueryRecordCount : maxQuery ,
}
2017-06-28 13:42:38 +02:00
c . JSON ( http . StatusOK , b )
2017-05-25 02:42:35 +02:00
}
2017-06-13 08:01:57 +02:00
2017-07-09 14:53:52 +02:00
/ * *
* @ api { post } / login / Login a user
2017-07-22 17:21:14 +02:00
* @ apiVersion 1.1 .1
2017-07-09 14:53:52 +02:00
* @ apiName Login
* @ apiGroup Users
*
* @ apiParam { String } username Username or Email .
* @ apiParam { String } password Password .
*
* @ apiSuccess { Boolean } ok The request is done without failing
* @ apiSuccess { String [ ] } infos Messages information relative to the request
* @ apiSuccess { Object } data The connected user object
*
* @ apiSuccessExample Success - Response :
* HTTP / 1.1 200 OK
* {
* data :
* [ {
* user_id : 1 ,
* username : "username" ,
* status : 1 ,
* token : "token" ,
* md5 : "" ,
* created_at : "date" ,
* liking_count : 0 ,
* liked_count : 0
* } ] ,
* infos : [ "Logged" , ... ] ,
* ok : true
* }
*
* @ apiUse RequestError
* /
2017-06-13 08:01:57 +02:00
// APILoginHandler : Login with API
// This is not an OAuth api like and shouldn't be used for anything except getting the API Token in order to not store a password
2017-06-28 13:42:38 +02:00
func APILoginHandler ( c * gin . Context ) {
2017-07-09 14:53:52 +02:00
c . Header ( "Content-Type" , "application/json" )
2017-07-02 18:00:12 +02:00
b := userValidator . LoginForm { }
2017-06-28 13:42:38 +02:00
messages := msg . GetMessages ( c )
contentType := c . Request . Header . Get ( "Content-type" )
2017-06-13 08:01:57 +02:00
if ! strings . HasPrefix ( contentType , "application/json" ) && ! strings . HasPrefix ( contentType , "multipart/form-data" ) && ! strings . HasPrefix ( contentType , "application/x-www-form-urlencoded" ) {
// TODO What should we do here ? upload is empty so we shouldn't
// create a torrent from it
2017-06-28 13:42:38 +02:00
messages . AddErrorT ( "errors" , "error_content_type_post" )
2017-06-13 08:01:57 +02:00
}
2017-06-28 13:42:38 +02:00
c . Bind ( & b )
2017-07-02 18:00:12 +02:00
validator . ValidateForm ( & b , messages )
2017-06-13 08:01:57 +02:00
if ! messages . HasErrors ( ) {
2017-07-02 18:00:12 +02:00
user , _ , errorUser := cookies . CreateUserAuthentication ( c , & b )
2017-06-13 08:01:57 +02:00
if errorUser == nil {
messages . AddInfo ( "infos" , "Logged" )
2017-08-01 14:47:27 +02:00
apiUtils . ResponseHandler ( c , user . ToJSON ( ) )
2017-06-13 08:01:57 +02:00
return
}
2017-06-28 13:42:38 +02:00
messages . Error ( errorUser )
2017-06-13 08:01:57 +02:00
}
2017-08-01 14:47:27 +02:00
apiUtils . ResponseHandler ( c )
2017-06-13 08:01:57 +02:00
}
2017-07-22 17:21:14 +02:00
/ * *
2017-10-16 11:33:14 +02:00
* @ api { get } / profile / Get a user profile
2017-07-22 17:21:14 +02:00
* @ apiVersion 1.1 .1
* @ apiName Profile
* @ apiGroup Users
*
* @ apiParam { Number } id User ID .
*
* @ apiSuccess { Boolean } ok The request is done without failing
* @ apiSuccess { String [ ] } infos Messages information relative to the request
* @ apiSuccess { Object } data The user object
*
* @ apiSuccessExample Success - Response :
* HTTP / 1.1 200 OK
* {
* data :
* [ {
* user_id : 1 ,
* username : "username" ,
* status : 1 ,
* md5 : "" ,
* created_at : "date" ,
* liking_count : 0 ,
* liked_count : 0
* } ] ,
* infos : [ "Logged" , ... ] ,
* ok : true
* }
*
* @ apiUse RequestError
* /
// APIProfileHandler : Get a public profile with API
func APIProfileHandler ( c * gin . Context ) {
c . Header ( "Content-Type" , "application/json" )
messages := msg . GetMessages ( c )
id , err := strconv . ParseUint ( c . Query ( "id" ) , 10 , 32 )
if err != nil {
id = 0
}
user , _ , errorUser := users . FindByID ( uint ( id ) )
if errorUser == nil {
user . APIToken = "" // We erase apitoken from public profile
2017-08-01 14:47:27 +02:00
apiUtils . ResponseHandler ( c , user . ToJSON ( ) )
2017-07-22 17:21:14 +02:00
return
}
messages . Error ( errorUser )
2017-08-01 14:47:27 +02:00
apiUtils . ResponseHandler ( c )
2017-07-22 17:21:14 +02:00
}
2017-07-28 05:46:40 +02:00
/ * *
2017-10-18 06:02:37 +02:00
* @ api { get } / user / Get a private user profile
2017-07-28 05:46:40 +02:00
* @ apiVersion 1.1 .1
* @ apiName Private Profile
* @ apiGroup Users
*
* @ apiParam { String } access_token Token sent by the OAuth API
*
* @ apiSuccess { Boolean } ok The request is done without failing
* @ apiSuccess { String [ ] } infos Messages information relative to the request
* @ apiSuccess { Object } data The connected user object
*
* @ apiSuccessExample Success - Response :
* HTTP / 1.1 200 OK
* {
* data :
* [ {
* user_id : 1 ,
* username : "username" ,
* status : 1 ,
* token : "token" ,
* md5 : "" ,
* created_at : "date" ,
* liking_count : 0 ,
* liked_count : 0
* } ] ,
* infos : [ "Logged" , ... ] ,
* ok : true
* }
*
* @ apiUse RequestError
* /
// APIOwnProfile : Get your own profile data. You need to be logged in through the OAuth API
func APIOwnProfile ( c * gin . Context ) {
c . Header ( "Content-Type" , "application/json" )
messages := msg . GetMessages ( c )
ctx , exist := c . Get ( "fosite" )
if exist {
oauthCtx := ctx . ( * fosite . AccessRequest )
client := oauthCtx . GetSession ( )
user , _ , _ , errorUser := users . FindByUsername ( client . GetSubject ( ) )
if errorUser == nil {
2017-08-01 14:47:27 +02:00
apiUtils . ResponseHandler ( c , user . ToJSON ( ) )
2017-07-28 05:46:40 +02:00
return
}
messages . Error ( errorUser )
2017-08-01 14:47:27 +02:00
apiUtils . ResponseHandler ( c )
2017-07-28 05:46:40 +02:00
return
}
c . AbortWithError ( http . StatusBadRequest , errors . New ( "Can't get your tokens" ) )
}
2017-06-13 08:01:57 +02:00
// APIRefreshTokenHandler : Refresh Token with API
2017-06-28 13:42:38 +02:00
func APIRefreshTokenHandler ( c * gin . Context ) {
2017-07-09 14:53:52 +02:00
c . Header ( "Content-Type" , "application/json" )
2017-06-28 13:42:38 +02:00
token := c . Request . Header . Get ( "Authorization" )
2017-07-22 16:14:38 +02:00
username := c . Query ( "username" )
2017-07-02 18:00:12 +02:00
user , _ , _ , _ , err := users . FindByAPITokenAndName ( token , username )
2017-06-28 13:42:38 +02:00
messages := msg . GetMessages ( c )
2017-06-13 08:01:57 +02:00
if err != nil {
2017-06-28 13:42:38 +02:00
messages . AddErrorT ( "errors" , "error_api_token" )
2017-06-13 08:01:57 +02:00
}
if ! messages . HasErrors ( ) {
user . APIToken , _ = crypto . GenerateRandomToken32 ( )
user . APITokenExpiry = time . Unix ( 0 , 0 )
2017-07-02 18:00:12 +02:00
_ , errorUser := user . UpdateRaw ( )
2017-06-13 08:01:57 +02:00
if errorUser == nil {
messages . AddInfoT ( "infos" , "profile_updated" )
2017-08-01 14:47:27 +02:00
apiUtils . ResponseHandler ( c , user . ToJSON ( ) )
2017-06-13 08:01:57 +02:00
return
}
2017-06-28 13:42:38 +02:00
messages . Error ( errorUser )
2017-06-13 08:01:57 +02:00
}
2017-08-01 14:47:27 +02:00
apiUtils . ResponseHandler ( c )
2017-06-13 08:01:57 +02:00
}
// APICheckTokenHandler : Check Token with API
2017-06-28 13:42:38 +02:00
func APICheckTokenHandler ( c * gin . Context ) {
2017-07-09 14:53:52 +02:00
c . Header ( "Content-Type" , "application/json" )
2017-06-28 13:42:38 +02:00
token := c . Request . Header . Get ( "Authorization" )
2017-07-22 16:14:38 +02:00
username := c . Query ( "username" )
2017-07-02 18:00:12 +02:00
user , _ , _ , _ , err := users . FindByAPITokenAndName ( token , username )
2017-06-28 13:42:38 +02:00
messages := msg . GetMessages ( c )
2017-06-13 08:01:57 +02:00
if err != nil {
2017-06-28 13:42:38 +02:00
messages . AddErrorT ( "errors" , "error_api_token" )
2017-06-13 08:01:57 +02:00
} else {
messages . AddInfo ( "infos" , "Logged" )
}
2017-08-01 14:47:27 +02:00
apiUtils . ResponseHandler ( c , user . ToJSON ( ) )
2017-06-13 08:01:57 +02:00
}