2024-10-01 17:38:43 +00:00
|
|
|
package server
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"net/http"
|
|
|
|
"net/url"
|
|
|
|
|
|
|
|
"somehole.com/common/oauth2/session"
|
|
|
|
)
|
|
|
|
|
|
|
|
const CallbackEndpoint = "/callback"
|
|
|
|
|
|
|
|
type CallbackError uint32
|
|
|
|
|
|
|
|
const (
|
|
|
|
CallbackOk CallbackError = iota
|
|
|
|
CallbackErrorUnimplemented
|
|
|
|
CallbackErrorUnauthorized
|
|
|
|
CallbackErrorServerError
|
|
|
|
)
|
|
|
|
|
2024-10-01 21:43:55 +00:00
|
|
|
func (ce CallbackError) Ok() bool {
|
|
|
|
return ce == CallbackOk
|
2024-10-01 17:38:43 +00:00
|
|
|
}
|
|
|
|
|
2024-10-01 21:43:55 +00:00
|
|
|
func (ce CallbackError) HttpStatus() (code int) {
|
|
|
|
switch ce {
|
2024-10-01 17:38:43 +00:00
|
|
|
case CallbackOk:
|
|
|
|
code = http.StatusOK
|
|
|
|
case CallbackErrorUnimplemented:
|
|
|
|
code = http.StatusInternalServerError
|
|
|
|
case CallbackErrorUnauthorized:
|
|
|
|
code = http.StatusUnauthorized
|
|
|
|
case CallbackErrorServerError:
|
|
|
|
code = http.StatusInternalServerError
|
2024-10-02 02:01:54 +00:00
|
|
|
default:
|
|
|
|
code = http.StatusInternalServerError
|
2024-10-01 17:38:43 +00:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-10-01 21:43:55 +00:00
|
|
|
func (ce CallbackError) String() (out string) {
|
|
|
|
switch ce {
|
2024-10-01 17:38:43 +00:00
|
|
|
case CallbackOk:
|
|
|
|
out = "authenticated"
|
|
|
|
case CallbackErrorUnimplemented:
|
|
|
|
out = "callback server unimplemented"
|
|
|
|
case CallbackErrorUnauthorized:
|
|
|
|
out = "user unauthorized"
|
|
|
|
case CallbackErrorServerError:
|
|
|
|
out = "internal server error"
|
2024-10-02 02:01:54 +00:00
|
|
|
default:
|
|
|
|
out = "unhandled error"
|
2024-10-01 17:38:43 +00:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-10-01 21:43:55 +00:00
|
|
|
func (ce CallbackError) ErrorResponse() []byte {
|
2024-10-01 17:38:43 +00:00
|
|
|
var msg string
|
2024-10-01 21:43:55 +00:00
|
|
|
switch ce {
|
2024-10-01 17:38:43 +00:00
|
|
|
default:
|
|
|
|
msg = "internal_server_error"
|
|
|
|
}
|
|
|
|
return mustMarshalJson(struct {
|
|
|
|
Error string `json:"error"`
|
|
|
|
}{
|
|
|
|
Error: msg,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
type CallbackRequest struct {
|
|
|
|
State session.State
|
|
|
|
Code session.Code
|
|
|
|
}
|
|
|
|
|
2024-10-01 22:57:46 +00:00
|
|
|
func (cr CallbackRequest) Request() Request {
|
|
|
|
return &cr
|
|
|
|
}
|
|
|
|
|
2024-10-01 17:38:43 +00:00
|
|
|
func (cr *CallbackRequest) Parse(data *url.Values) (err error) {
|
|
|
|
if !data.Has("code") {
|
|
|
|
err = fmt.Errorf("missing code paramater")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if !data.Has("state") {
|
|
|
|
err = fmt.Errorf("missing state parameter")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
cr.State = session.State(data.Get("state"))
|
|
|
|
cr.Code = session.Code(data.Get("code"))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
type CallbackResponse struct {
|
|
|
|
Message string `json:"message"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cr *CallbackResponse) Response() []byte {
|
|
|
|
return mustMarshalJson(cr)
|
|
|
|
}
|
|
|
|
|
|
|
|
type UnimplementedCallbackServer struct{}
|
|
|
|
|
|
|
|
func (u UnimplementedCallbackServer) mustEmbedUnimplementedCallbackServer() {}
|
|
|
|
|
2024-10-01 21:43:55 +00:00
|
|
|
func (u UnimplementedCallbackServer) Callback(req *CallbackRequest) (res *CallbackResponse, errRes ErrorResponse) {
|
|
|
|
errRes = CallbackErrorUnimplemented
|
2024-10-01 17:38:43 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
type CallbackServer interface {
|
|
|
|
mustEmbedUnimplementedCallbackServer()
|
2024-10-01 21:43:55 +00:00
|
|
|
Callback(*CallbackRequest) (*CallbackResponse, ErrorResponse)
|
2024-10-01 17:38:43 +00:00
|
|
|
}
|