-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add ServiceNow, so far just with logging in via OAuth
- Loading branch information
Showing
6 changed files
with
149 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
(* For this demo, it's necessary to create serviceNowSecrets.ur, | ||
* defining [instance], [client_id], and [client_secret]. *) | ||
|
||
structure A = ServiceNow.ThreeLegged(struct | ||
open ServiceNowSecrets | ||
val https = False | ||
val onCompletion = return <xml>Done.</xml> | ||
val scopes = ServiceNow.Scope.empty | ||
end) | ||
structure S = ServiceNow.Make(A) | ||
|
||
val main = | ||
toko <- A.token; | ||
case toko of | ||
None => return <xml><body><a link={A.authorize}>Log into ServiceNow</a></body></xml> | ||
| Some _ => return <xml><body>You are logged in.</body></xml> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
library ../src/ur | ||
rewrite all ServiceNowDemo/* | ||
database dbname=serviceNowDemo | ||
sql serviceNowDemo.sql | ||
safeGetDefault | ||
allow url https://* | ||
prefix http://localhost:8080/ | ||
|
||
serviceNowSecrets | ||
serviceNowDemo |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
val main : transaction page |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,3 +31,4 @@ zenefits | |
netSuite | ||
chatgpt | ||
smartsheet | ||
serviceNow |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
open Json | ||
|
||
structure Scope = struct | ||
type t = Scopes.t [] | ||
val empty = Scopes.empty | ||
val union = Scopes.union | ||
val toString = Scopes.toString {} | ||
|
||
val readonly = Scopes.disjoint empty | ||
end | ||
|
||
signature AUTH = sig | ||
val token : transaction (option string) | ||
end | ||
|
||
functor Make(M : AUTH) = struct | ||
open M | ||
end | ||
|
||
functor ThreeLegged(M : sig | ||
val instance : string | ||
val client_id : string | ||
val client_secret : string | ||
val https : bool | ||
|
||
val scopes : Scope.t | ||
val onCompletion : transaction page | ||
end) = struct | ||
open M | ||
|
||
table secrets : { Secret : int, | ||
Token : string, | ||
Expires : time } | ||
PRIMARY KEY Secret | ||
|
||
task periodic 60 = fn () => | ||
tm <- now; | ||
dml (DELETE FROM secrets | ||
WHERE Expires < {[addSeconds tm (-60)]}) | ||
|
||
cookie user : int | ||
|
||
fun withToken {Token = tok, Expiration = seconds, ...} = | ||
case seconds of | ||
None => error <xml>Missing token expiration in OAuth response</xml> | ||
| Some seconds => | ||
secret <- rand; | ||
tm <- now; | ||
dml (INSERT INTO secrets(Secret, Token, Expires) | ||
VALUES ({[secret]}, {[tok]}, {[addSeconds tm (seconds * 3 / 4)]})); | ||
setCookie user {Value = secret, | ||
Expires = None, | ||
Secure = https} | ||
|
||
open Oauth.Make(struct | ||
open M | ||
|
||
val authorize_url = bless ("https://" ^ instance ^ ".service-now.com/oauth_auth.do") | ||
val access_token_url = bless ("https://" ^ instance ^ ".service-now.com/oauth_token.do") | ||
|
||
val withToken = withToken | ||
val scope = None | ||
val nameForScopeParameter = None | ||
val parseTokenResponse = None | ||
val hosted_domain = None | ||
end) | ||
|
||
val token = | ||
c <- getCookie user; | ||
case c of | ||
None => return None | ||
| Some n => | ||
oneOrNoRowsE1 (SELECT (secrets.Token) | ||
FROM secrets | ||
WHERE secrets.Secret = {[n]} | ||
AND secrets.Expires > CURRENT_TIMESTAMP) | ||
|
||
val logout = clearCookie user | ||
|
||
val status = | ||
toko <- token; | ||
li <- source (Option.isSome toko); | ||
cur <- currentUrl; | ||
return <xml> | ||
<dyn signal={liV <- signal li; | ||
if liV then | ||
return <xml><button value="Log out of ServiceNow" | ||
onclick={fn _ => rpc logout; set li False}/></xml> | ||
else | ||
return <xml><button value="Log into ServiceNow" | ||
onclick={fn _ => redirect (url authorize)}/></xml>}/> | ||
</xml> | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
structure Scope : sig | ||
type t | ||
val empty : t | ||
val union : t -> t -> t | ||
val readonly : t -> bool | ||
end | ||
|
||
signature AUTH = sig | ||
val token : transaction (option string) | ||
end | ||
|
||
functor ThreeLegged(M : sig | ||
val instance : string | ||
val client_id : string | ||
val client_secret : string | ||
val https : bool | ||
|
||
val scopes : Scope.t | ||
val onCompletion : transaction page | ||
end) : sig | ||
val token : transaction (option string) | ||
val authorize : transaction page | ||
val status : transaction xbody | ||
val logout : transaction unit | ||
end | ||
|
||
functor Make(M : AUTH) : sig | ||
end |