Implemented user capabilities
parent
583d036e8a
commit
5bae9bf6ef
|
@ -24,6 +24,12 @@ IN: http.tests
|
|||
[ "/bar" ] [ "http://foo.com/bar" url>path ] unit-test
|
||||
[ "/bar" ] [ "/bar" url>path ] unit-test
|
||||
|
||||
[ "a=b&a=c" ] [ { { "a" { "b" "c" } } } assoc>query ] unit-test
|
||||
|
||||
[ H{ { "a" "b" } } ] [ "a=b" query>assoc ] unit-test
|
||||
|
||||
[ H{ { "a" { "b" "c" } } } ] [ "a=b&a=c" query>assoc ] unit-test
|
||||
|
||||
: lf>crlf "\n" split "\r\n" join ;
|
||||
|
||||
STRING: read-request-test-1
|
||||
|
|
|
@ -119,21 +119,41 @@ IN: http
|
|||
header-value>string check-header-string write crlf
|
||||
] assoc-each crlf ;
|
||||
|
||||
: add-query-param ( value key assoc -- )
|
||||
[
|
||||
at [
|
||||
{
|
||||
{ [ dup string? ] [ swap 2array ] }
|
||||
{ [ dup array? ] [ swap suffix ] }
|
||||
{ [ dup not ] [ drop ] }
|
||||
} cond
|
||||
] when*
|
||||
] 2keep set-at ;
|
||||
|
||||
: query>assoc ( query -- assoc )
|
||||
dup [
|
||||
"&" split [
|
||||
"=" split1 [ dup [ url-decode ] when ] bi@
|
||||
] H{ } map>assoc
|
||||
"&" split H{ } clone [
|
||||
[
|
||||
>r "=" split1 [ dup [ url-decode ] when ] bi@ swap r>
|
||||
add-query-param
|
||||
] curry each
|
||||
] keep
|
||||
] when ;
|
||||
|
||||
: assoc>query ( hash -- str )
|
||||
[
|
||||
[ url-encode ]
|
||||
[ dup number? [ number>string ] when url-encode ]
|
||||
bi*
|
||||
"=" swap 3append
|
||||
] { } assoc>map
|
||||
"&" join ;
|
||||
{
|
||||
{ [ dup number? ] [ number>string ] }
|
||||
{ [ dup string? ] [ 1array ] }
|
||||
{ [ dup sequence? ] [ ] }
|
||||
} cond
|
||||
] assoc-map
|
||||
[
|
||||
[
|
||||
>r url-encode r>
|
||||
[ url-encode "=" swap 3append , ] with each
|
||||
] assoc-each
|
||||
] { } make "&" join ;
|
||||
|
||||
TUPLE: cookie name value path domain expires max-age http-only ;
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
! Copyright (C) 2008 Slava Pestov.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: kernel sequences accessors namespaces combinators
|
||||
locals db.tuples
|
||||
USING: kernel sequences accessors namespaces combinators words
|
||||
assocs locals db.tuples arrays splitting strings qualified
|
||||
|
||||
http.server.templating.chloe
|
||||
http.server.boilerplate
|
||||
http.server.auth.providers
|
||||
|
@ -10,17 +11,26 @@ http.server.auth.login
|
|||
http.server.auth
|
||||
http.server.forms
|
||||
http.server.components.inspector
|
||||
http.server.components
|
||||
http.server.validators
|
||||
http.server.sessions
|
||||
http.server.actions
|
||||
http.server.crud
|
||||
http.server ;
|
||||
EXCLUDE: http.server.components => string? number? ;
|
||||
IN: http.server.auth.admin
|
||||
|
||||
: admin-template ( name -- template )
|
||||
"resource:extra/http/server/auth/admin/" swap ".xml" 3append <chloe> ;
|
||||
|
||||
: words>strings ( seq -- seq' )
|
||||
[ [ word-vocabulary ] [ drop ":" ] [ word-name ] tri 3append ] map ;
|
||||
|
||||
: strings>words ( seq -- seq' )
|
||||
[ ":" split1 swap lookup ] map ;
|
||||
|
||||
: <capabilities> ( id -- component )
|
||||
capabilities get words>strings <menu> ;
|
||||
|
||||
: <new-user-form> ( -- form )
|
||||
"user" <form>
|
||||
"new-user" admin-template >>edit-template
|
||||
|
@ -28,8 +38,8 @@ IN: http.server.auth.admin
|
|||
"realname" <string> add-field
|
||||
"new-password" <password> t >>required add-field
|
||||
"verify-password" <password> t >>required add-field
|
||||
"email" <email> add-field ;
|
||||
! "capabilities" <capabilities> add-field ;
|
||||
"email" <email> add-field
|
||||
"capabilities" <capabilities> add-field ;
|
||||
|
||||
: <edit-user-form> ( -- form )
|
||||
"user" <form>
|
||||
|
@ -40,8 +50,8 @@ IN: http.server.auth.admin
|
|||
"new-password" <password> add-field
|
||||
"verify-password" <password> add-field
|
||||
"email" <email> add-field
|
||||
"profile" <inspector> add-field ;
|
||||
! "capabilities" <capabilities> add-field ;
|
||||
"profile" <inspector> add-field
|
||||
"capabilities" <capabilities> add-field ;
|
||||
|
||||
: <user-list-form> ( -- form )
|
||||
"user-list" <form>
|
||||
|
@ -102,6 +112,7 @@ IN: http.server.auth.admin
|
|||
[ realname>> "realname" set-value ]
|
||||
[ email>> "email" set-value ]
|
||||
[ profile>> "profile" set-value ]
|
||||
[ capabilities>> words>strings "capabilities" set-value ]
|
||||
} cleave
|
||||
] >>init
|
||||
|
||||
|
@ -122,6 +133,11 @@ IN: http.server.auth.admin
|
|||
"new-password" value >>encoded-password
|
||||
] unless
|
||||
|
||||
"capabilities" value {
|
||||
{ [ dup string? ] [ 1array ] }
|
||||
{ [ dup array? ] [ ] }
|
||||
} cond strings>words >>capabilities
|
||||
|
||||
update-tuple
|
||||
|
||||
next f <standard-redirect>
|
||||
|
@ -157,3 +173,9 @@ can-administer-users? define-capability
|
|||
"admin" admin-template >>template
|
||||
{ can-administer-users? } <protected>
|
||||
] ;
|
||||
|
||||
: make-admin ( username -- )
|
||||
<user>
|
||||
select-tuple
|
||||
[ can-administer-users? suffix ] change-capabilities
|
||||
update-tuple ;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
|
||||
|
||||
<t:style include="resource:extra/http/server/auth/admin/admin.css" />
|
||||
<t:style t:include="resource:extra/http/server/auth/admin/admin.css" />
|
||||
|
||||
<div class="navbar">
|
||||
<t:a t:href="$user-admin">List Users</t:a>
|
||||
|
|
|
@ -35,6 +35,11 @@
|
|||
<td><t:edit t:component="email" /></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th class="field-label big-field-label">Capabilities:</th>
|
||||
<td><t:edit t:component="capabilities" /></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th class="field-label">Profile:</th>
|
||||
<td><t:view t:component="profile" /></td>
|
||||
|
|
|
@ -32,6 +32,11 @@
|
|||
<th class="field-label">E-mail:</th>
|
||||
<td><t:edit t:component="email" /></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th class="field-label big-field-label">Capabilities:</th>
|
||||
<td><t:edit t:component="capabilities" /></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: accessors quotations assocs kernel splitting
|
||||
base64 html.elements io combinators http.server
|
||||
http.server.auth.providers http.server.auth.providers.null
|
||||
http.server.auth.providers http.server.auth.login
|
||||
http sequences ;
|
||||
IN: http.server.auth.basic
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
! Copyright (c) 2008 Slava Pestov
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: accessors quotations assocs kernel splitting
|
||||
combinators sequences namespaces hashtables
|
||||
combinators sequences namespaces hashtables sets
|
||||
fry arrays threads locals qualified random
|
||||
io
|
||||
io.sockets
|
||||
|
@ -364,7 +364,7 @@ C: <protected> protected
|
|||
"$login/login" f <standard-redirect> ;
|
||||
|
||||
: check-capabilities ( responder user -- ? )
|
||||
[ capabilities>> ] [ profile>> ] bi* '[ , at ] all? ;
|
||||
[ capabilities>> ] bi@ subset? ;
|
||||
|
||||
M: protected call-responder* ( path responder -- response )
|
||||
uid dup [
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
IN: http.server.auth.providers.assoc.tests
|
||||
USING: http.server.actions http.server.auth.providers
|
||||
http.server.auth.providers.assoc tools.test
|
||||
namespaces accessors kernel ;
|
||||
http.server.auth.providers.assoc http.server.auth.login
|
||||
tools.test namespaces accessors kernel ;
|
||||
|
||||
<action> <login>
|
||||
<users-in-memory> >>users
|
||||
|
|
|
@ -13,6 +13,7 @@ user "USERS"
|
|||
{ "salt" "SALT" INTEGER +not-null+ }
|
||||
{ "email" "EMAIL" { VARCHAR 256 } }
|
||||
{ "ticket" "TICKET" { VARCHAR 256 } }
|
||||
{ "capabilities" "CAPABILITIES" FACTOR-BLOB }
|
||||
{ "profile" "PROFILE" FACTOR-BLOB }
|
||||
{ "deleted" "DELETED" INTEGER +not-null+ }
|
||||
} define-persistent
|
||||
|
|
|
@ -4,7 +4,10 @@ USING: kernel accessors random math.parser locals
|
|||
sequences math ;
|
||||
IN: http.server.auth.providers
|
||||
|
||||
TUPLE: user username realname password salt email ticket profile deleted changed? ;
|
||||
TUPLE: user
|
||||
username realname
|
||||
password salt
|
||||
email ticket capabilities profile deleted changed? ;
|
||||
|
||||
: <user> ( username -- user )
|
||||
user new
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: accessors namespaces kernel io math.parser assocs classes
|
||||
words classes.tuple arrays sequences splitting mirrors
|
||||
hashtables fry combinators continuations math
|
||||
hashtables fry locals combinators continuations math
|
||||
calendar.format html.elements xml.entities
|
||||
http.server.validators ;
|
||||
IN: http.server.components
|
||||
|
@ -18,10 +18,11 @@ TUPLE: field type ;
|
|||
|
||||
C: <field> field
|
||||
|
||||
M: field render-view* drop escape-string write ;
|
||||
M: field render-view*
|
||||
drop escape-string write ;
|
||||
|
||||
M: field render-edit*
|
||||
<input type>> =type [ =id ] [ =name ] bi =value input/> ;
|
||||
<input type>> =type =name =value input/> ;
|
||||
|
||||
: render-error ( message -- )
|
||||
<span "error" =class span> escape-string write </span> ;
|
||||
|
@ -348,8 +349,8 @@ M: choice-renderer render-view*
|
|||
escape-string write
|
||||
</option> ;
|
||||
|
||||
: render-options ( text selected -- )
|
||||
[ [ drop ] [ member? ] 2bi render-option ] curry each ;
|
||||
: render-options ( options selected -- )
|
||||
'[ dup , member? render-option ] each ;
|
||||
|
||||
M: choice-renderer render-edit*
|
||||
<select swap =name select>
|
||||
|
@ -365,11 +366,16 @@ TUPLE: choice < string ;
|
|||
! Menu
|
||||
TUPLE: menu-renderer choices size ;
|
||||
|
||||
C: <menu-renderer> menu-renderer
|
||||
: <menu-renderer> ( choices -- renderer )
|
||||
5 menu-renderer boa ;
|
||||
|
||||
M: menu-renderer render-edit*
|
||||
<select dup size>> [ number>string =size ] when* swap =name select>
|
||||
choices>> render-options
|
||||
M:: menu-renderer render-edit* ( value id renderer -- )
|
||||
<select
|
||||
renderer size>> [ number>string =size ] when*
|
||||
id =name
|
||||
"true" =multiple
|
||||
select>
|
||||
renderer choices>> value render-options
|
||||
</select> ;
|
||||
|
||||
TUPLE: menu < string ;
|
||||
|
@ -377,3 +383,22 @@ TUPLE: menu < string ;
|
|||
: <menu> ( id choices -- component )
|
||||
swap menu new-string
|
||||
swap <menu-renderer> >>renderer ;
|
||||
|
||||
! Checkboxes
|
||||
TUPLE: checkbox-renderer label ;
|
||||
|
||||
C: <checkbox-renderer> checkbox-renderer
|
||||
|
||||
M: checkbox-renderer render-edit*
|
||||
<input
|
||||
"checkbox" =type
|
||||
swap =id
|
||||
swap [ "true" =selected ] when
|
||||
input>
|
||||
label>> escape-string write
|
||||
</input> ;
|
||||
|
||||
TUPLE: checkbox < string ;
|
||||
|
||||
: <checkbox> ( id label -- component )
|
||||
checkbox swap <checkbox-renderer> new-component ;
|
||||
|
|
|
@ -7,7 +7,7 @@ logging calendar.format accessors io.encodings.binary fry ;
|
|||
IN: http.server.static
|
||||
|
||||
! special maps mime types to quots with effect ( path -- )
|
||||
TUPLE: file-responder root hook special ;
|
||||
TUPLE: file-responder root hook special allow-listings ;
|
||||
|
||||
: modified-since? ( filename -- ? )
|
||||
request get "if-modified-since" header dup [
|
||||
|
@ -19,8 +19,14 @@ TUPLE: file-responder root hook special ;
|
|||
: <304> ( -- response )
|
||||
304 "Not modified" <trivial-response> ;
|
||||
|
||||
: <403> ( -- response )
|
||||
403 "Forbidden" <trivial-response> ;
|
||||
|
||||
: <file-responder> ( root hook -- responder )
|
||||
H{ } clone file-responder boa ;
|
||||
file-responder new
|
||||
swap >>hook
|
||||
swap >>root
|
||||
H{ } clone >>special ;
|
||||
|
||||
: <static> ( root -- responder )
|
||||
[
|
||||
|
@ -65,7 +71,11 @@ TUPLE: file-responder root hook special ;
|
|||
] simple-html-document ;
|
||||
|
||||
: list-directory ( directory -- response )
|
||||
'[ , directory. ] <html-content> ;
|
||||
file-responder get allow-listings>> [
|
||||
'[ , directory. ] <html-content>
|
||||
] [
|
||||
drop <403>
|
||||
] if ;
|
||||
|
||||
: find-index ( filename -- path )
|
||||
"index.html" append-path dup exists? [ drop f ] unless ;
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
body, button {
|
||||
font:9pt "Lucida Grande", "Lucida Sans Unicode", verdana, geneva, sans-serif;
|
||||
color:#444;
|
||||
}
|
||||
|
||||
.link-button {
|
||||
padding: 0px;
|
||||
background: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
a, .link {
|
||||
color: #222;
|
||||
border-bottom:1px dotted #666;
|
||||
text-decoration:none;
|
||||
}
|
||||
|
||||
a:hover, .link:hover {
|
||||
border-bottom:1px solid #66a;
|
||||
}
|
||||
|
||||
.error { color: #a00; }
|
||||
|
||||
.field-label {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.inline {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
background-color: #eee;
|
||||
padding: 5px;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.big-field-label {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.description {
|
||||
border: 1px dashed #ccc;
|
||||
background-color: #f5f5f5;
|
||||
padding: 5px;
|
||||
font-size: 150%;
|
||||
color: #000000;
|
||||
}
|
|
@ -12,56 +12,7 @@
|
|||
|
||||
<t:style t:include="resource:extra/xmode/code2html/stylesheet.css" />
|
||||
|
||||
<t:style>
|
||||
body, button {
|
||||
font:9pt "Lucida Grande", "Lucida Sans Unicode", verdana, geneva, sans-serif;
|
||||
color:#444;
|
||||
}
|
||||
|
||||
.link-button {
|
||||
padding: 0px;
|
||||
background: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
a, .link {
|
||||
color: #222;
|
||||
border-bottom:1px dotted #666;
|
||||
text-decoration:none;
|
||||
}
|
||||
|
||||
a:hover, .link:hover {
|
||||
border-bottom:1px solid #66a;
|
||||
}
|
||||
|
||||
.error { color: #a00; }
|
||||
|
||||
.field-label {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.inline {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
background-color: #eee;
|
||||
padding: 5px;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.big-field-label {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.description {
|
||||
border: 1px dashed #ccc;
|
||||
background-color: #f5f5f5;
|
||||
padding: 5px;
|
||||
font-size: 150%;
|
||||
color: #000000;
|
||||
}
|
||||
</t:style>
|
||||
<t:style t:include="resource:extra/webapps/factor-website/page.css" />
|
||||
|
||||
<t:write-style />
|
||||
</head>
|
||||
|
|
|
@ -2,10 +2,7 @@
|
|||
|
||||
<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
|
||||
|
||||
<t:comment>
|
||||
<t:atom title="Planet Factor - Atom" href="$planet/feed.xml" />
|
||||
</t:comment>
|
||||
<t:style include="resource:extra/webapps/planet/planet.css" />
|
||||
<t:style t:include="resource:extra/webapps/planet/planet.css" />
|
||||
|
||||
<div class="navbar">
|
||||
<t:a t:href="$planet-factor/list">Front Page</t:a>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
|
||||
|
||||
<t:style include="resource:extra/webapps/todo/todo.css" />
|
||||
<t:style t:include="resource:extra/webapps/todo/todo.css" />
|
||||
|
||||
<div class="navbar">
|
||||
<t:a t:href="$todo-list/list">List Items</t:a>
|
||||
|
|
Loading…
Reference in New Issue