1
- use std:: io:: IoResult ;
2
-
3
1
use conduit:: { Request , Response } ;
4
2
use conduit_router:: RequestParams ;
5
3
use conduit_json_parser;
6
4
use pg:: { PostgresConnection , PostgresRow } ;
7
5
8
6
use app:: { App , RequestApp } ;
9
- use user:: RequestUser ;
10
- use util:: RequestUtils ;
7
+ use user:: { RequestUser , User } ;
8
+ use util:: { RequestUtils , CargoResult , Require , internal} ;
9
+ use util:: errors:: { NotFound , CargoError } ;
11
10
12
11
#[ deriving( Encodable ) ]
13
12
pub struct Package {
@@ -23,16 +22,27 @@ impl Package {
23
22
}
24
23
}
25
24
26
- pub fn find ( app : & App , slug : & str ) -> Option < Package > {
25
+ pub fn find ( app : & App , slug : & str ) -> CargoResult < Package > {
27
26
let conn = app. db ( ) ;
28
- let stmt = conn. prepare ( "SELECT * FROM packages WHERE slug = $1 LIMIT 1" )
29
- . unwrap ( ) ;
30
- stmt. query ( [ & slug] ) . unwrap ( ) . next ( ) . map ( |row| {
31
- Package {
32
- id : row. get ( "slug" ) ,
33
- name : row. get ( "name" ) ,
27
+ let stmt = try!( conn. prepare ( "SELECT * FROM packages \
28
+ WHERE slug = $1 LIMIT 1") ) ;
29
+ match try!( stmt. query ( [ & slug] ) ) . next ( ) {
30
+ Some ( row) => Ok ( Package :: from_row ( & row) ) ,
31
+ None => Err ( NotFound . box_error ( ) ) ,
32
+ }
33
+ }
34
+
35
+ fn name_to_slug ( name : & str ) -> String {
36
+ name. chars ( ) . filter_map ( |c| {
37
+ match c {
38
+ 'A' .. 'Z' |
39
+ 'a' .. 'z' |
40
+ '0' .. '9' |
41
+ '-' | '_' => Some ( c. to_lowercase ( ) ) ,
42
+ _ => None
43
+
34
44
}
35
- } )
45
+ } ) . collect ( )
36
46
}
37
47
}
38
48
@@ -52,20 +62,19 @@ pub fn setup(conn: &PostgresConnection) {
52
62
[ & "Test2" , & "test2" ] ) . unwrap ( ) ;
53
63
}
54
64
55
- pub fn index ( req : & mut Request ) -> IoResult < Response > {
65
+ pub fn index ( req : & mut Request ) -> CargoResult < Response > {
56
66
let limit = 10i64 ;
57
67
let offset = 0i64 ;
58
68
let conn = req. app ( ) . db ( ) ;
59
- let stmt = conn. prepare ( "SELECT * FROM packages LIMIT $1 OFFSET $2" )
60
- . unwrap ( ) ;
69
+ let stmt = try!( conn. prepare ( "SELECT * FROM packages LIMIT $1 OFFSET $2" ) ) ;
61
70
62
71
let mut pkgs = Vec :: new ( ) ;
63
- for row in stmt. query ( [ & limit, & offset] ) . unwrap ( ) {
72
+ for row in try! ( stmt. query ( [ & limit, & offset] ) ) {
64
73
pkgs. push ( Package :: from_row ( & row) ) ;
65
74
}
66
75
67
- let stmt = conn. prepare ( "SELECT COUNT(*) FROM packages" ) . unwrap ( ) ;
68
- let row = stmt. query ( [ ] ) . unwrap ( ) . next ( ) . unwrap ( ) ;
76
+ let stmt = try! ( conn. prepare ( "SELECT COUNT(*) FROM packages" ) ) ;
77
+ let row = try! ( stmt. query ( [ ] ) ) . next ( ) . unwrap ( ) ;
69
78
let total = row. get ( 0 u) ;
70
79
71
80
#[ deriving( Encodable ) ]
@@ -79,20 +88,12 @@ pub fn index(req: &mut Request) -> IoResult<Response> {
79
88
} ) )
80
89
}
81
90
82
- pub fn show ( req : & mut Request ) -> IoResult < Response > {
91
+ pub fn show ( req : & mut Request ) -> CargoResult < Response > {
83
92
let slug = req. params ( ) [ "package_id" ] ;
84
- let conn = req. app ( ) . db ( ) ;
85
- let stmt = conn. prepare ( "SELECT * FROM packages WHERE slug = $1 LIMIT 1" )
86
- . unwrap ( ) ;
87
- let row = match stmt. query ( [ & slug. as_slice ( ) ] ) . unwrap ( ) . next ( ) {
88
- Some ( row) => row,
89
- None => return Ok ( req. not_found ( ) ) ,
90
- } ;
93
+ let pkg = try!( Package :: find ( req. app ( ) , slug. as_slice ( ) ) ) ;
91
94
92
95
#[ deriving( Encodable ) ]
93
96
struct R { package : Package }
94
-
95
- let pkg = Package :: from_row ( & row) ;
96
97
Ok ( req. json ( & R { package : pkg } ) )
97
98
}
98
99
@@ -104,25 +105,49 @@ pub struct UpdatePackage {
104
105
name : String ,
105
106
}
106
107
107
- pub fn update ( req : & mut Request ) -> IoResult < Response > {
108
- if req. user ( ) . is_none ( ) {
109
- return Ok ( req. unauthorized ( ) )
110
- }
108
+ pub fn update ( req : & mut Request ) -> CargoResult < Response > {
109
+ try!( req. user ( ) ) ;
111
110
let slug = req. params ( ) [ "package_id" ] ;
112
- let mut pkg = match Package :: find ( req. app ( ) , slug. as_slice ( ) ) {
113
- Some ( pkg) => pkg,
114
- None => return Ok ( req. not_found ( ) ) ,
111
+ let mut pkg = try!( Package :: find ( req. app ( ) , slug. as_slice ( ) ) ) ;
112
+
113
+ let conn = req. app ( ) . db ( ) ;
114
+ let update = conduit_json_parser:: json_params :: < UpdateRequest > ( req) ;
115
+ pkg. name = update. unwrap ( ) . package . name . clone ( ) ;
116
+ try!( conn. execute ( "UPDATE packages SET name = $1 WHERE slug = $2" ,
117
+ [ & pkg. name . as_slice ( ) , & slug. as_slice ( ) ] ) ) ;
118
+
119
+ #[ deriving( Encodable ) ]
120
+ struct R { package : Package }
121
+ Ok ( req. json ( & R { package : pkg } ) )
122
+ }
123
+
124
+ #[ deriving( Decodable ) ]
125
+ pub struct NewRequest { package : NewPackage }
126
+
127
+ #[ deriving( Decodable ) ]
128
+ pub struct NewPackage {
129
+ name : String ,
130
+ }
131
+
132
+ pub fn new ( req : & mut Request ) -> CargoResult < Response > {
133
+ let app = req. app ( ) ;
134
+ let db = app. db ( ) ;
135
+ let tx = try!( db. transaction ( ) ) ;
136
+ let _user = {
137
+ let header = try!( req. headers ( ) . find ( "X-Cargo-Auth" ) . require ( || {
138
+ internal ( "missing X-Cargo-Auth header" )
139
+ } ) ) ;
140
+ try!( User :: find_by_api_token ( app, header. get ( 0 ) . as_slice ( ) ) )
115
141
} ;
116
- {
117
- let conn = req. app ( ) . db ( ) ;
118
- let update = conduit_json_parser:: json_params :: < UpdateRequest > ( req) ;
119
- pkg. name = update. unwrap ( ) . package . name . clone ( ) ;
120
- conn. execute ( "UPDATE packages SET name = $1 WHERE slug = $2" ,
121
- [ & pkg. name . as_slice ( ) , & slug. as_slice ( ) ] )
122
- . unwrap ( ) ;
123
- }
142
+
143
+ let update = conduit_json_parser:: json_params :: < NewRequest > ( req) . unwrap ( ) ;
144
+ let name = update. package . name . as_slice ( ) ;
145
+ let slug = Package :: name_to_slug ( name) ;
146
+ try!( tx. execute ( "INSERT INTO packages (name, slug) VALUES ($1, $2)" ,
147
+ [ & name, & slug] ) ) ;
124
148
125
149
#[ deriving( Encodable ) ]
126
150
struct R { package : Package }
151
+ let pkg = try!( Package :: find ( app, slug. as_slice ( ) ) ) ;
127
152
Ok ( req. json ( & R { package : pkg } ) )
128
153
}
0 commit comments