Skip to content

Commit

Permalink
Merge pull request #16 from sebastianconcept/13-Add-authenticity-toke…
Browse files Browse the repository at this point in the history
…n-as-hidden-input-for-forms

fixes session cookie and authenticity_token
  • Loading branch information
sebastianconcept authored Feb 24, 2024
2 parents 1b566c8 + 684b1a5 commit 786e299
Show file tree
Hide file tree
Showing 7 changed files with 274 additions and 52 deletions.
23 changes: 20 additions & 3 deletions Ride-Builder/RideAppClassHelper.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,16 @@ RideAppClassHelper class >> newSessionWith_UrlMethodFor: aSymbol [
"Answer a new {1}App session with the given sessionId and url."
^ {1}Session newWith: sessionId url: anUrl
^ self sessionClass newWith: sessionId url: anUrl
' format: { aSymbol }
]

{ #category : #accessing }
RideAppClassHelper class >> sessionClassMethodFor: aSymbol [

^ 'sessionClass
^ {1}Session
' format: { aSymbol }
]

Expand Down Expand Up @@ -90,11 +99,18 @@ RideAppClassHelper >> addInstallMethodTo: aClass for: aSymbol [

{ #category : #actions }
RideAppClassHelper >> addNewSessionWith_UrlMethodTo: aClass for: aSymbol [

self deprecated: 'not used'.
aClass class compile: (self class newSessionWith_UrlMethodFor: aSymbol).
aClass class organization classify: #'newSessionWith:url:' under: 'actions'
]

{ #category : #actions }
RideAppClassHelper >> addSessionClassMethodTo: aClass for: aSymbol [

aClass class compile: (self class sessionClassMethodFor: aSymbol).
aClass class organization classify: #sessionClass under: 'accessing'
]

{ #category : #accessing }
RideAppClassHelper >> classNameFor: aSymbol [

Expand All @@ -114,7 +130,8 @@ RideAppClassHelper >> for: aSymbol [
| appClass |
appClass := super for: aSymbol.

self addNewSessionWith_UrlMethodTo: appClass for: aSymbol.
self addSessionClassMethodTo: appClass for: aSymbol.
"self addNewSessionWith_UrlMethodTo: appClass for: aSymbol."
self addInstallMethodTo: appClass for: aSymbol.
self addApplicationResourceClassMethodTo: appClass for: aSymbol.
self addInitializeServerMethodTo: appClass for: aSymbol.
Expand Down
28 changes: 28 additions & 0 deletions Ride-Builder/RideAppHelper.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,31 @@ RideAppHelper class >> fourZeroFourContentFor: aSymbol [
' format: { aSymbol }
]

{ #category : #accessing }
RideAppHelper class >> fourZeroOneContentFor: aSymbol [

^ '<!DOCTYPE html>
<html>
<head>
<title>Unauthorized (401)</title>
<meta name="viewport" content="width=device-width,initial-scale=1" />
</head>
<body class="ride-default-error-page">
<div class="dialog">
<div>
<h1>Unauthorized</h1>
<p>The authorization for the requested content was found to be invalid.</p>
</div>
<p>
If you are the {1} application owner check the logs for more information.
</p>
</div>
</body>
</html>
' format: { aSymbol }
]

{ #category : #accessing }
RideAppHelper class >> gitignoreContent [

Expand Down Expand Up @@ -581,6 +606,9 @@ RideAppHelper >> ensureTemplatesSharedOn: directory for: aSymbol [

directory ensureCreateDirectory.

directory / '401.html.stt' writeStreamDo: [ :stream |
stream nextPutAll: (self class fourZeroOneContentFor: aSymbol) ].

directory / '404.html.stt' writeStreamDo: [ :stream |
stream nextPutAll: (self class fourZeroFourContentFor: aSymbol) ].

Expand Down
6 changes: 3 additions & 3 deletions Ride-Builder/RideAppHomeTemplateHelper.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ Class {
RideAppHomeTemplateHelper class >> indexHTMLTemplateFor: aSymbol [

^ '<div>
<h1>Welcome to <st= self webAppName ></h1>
<p>This page was rendered by a STTemplate generated for <st= self webAppName >.</p>
<p>Find my source in <code><st= self templatePath ></code></p>
<h1>Welcome to <%= self webAppName %></h1>
<p>This page was rendered by a STTemplate generated for <%= self webAppName %>.</p>
<p>Find my source in <code><%= self templatePath %></code></p>
</div>' format: { aSymbol }
]

Expand Down
61 changes: 43 additions & 18 deletions Ride/RidePresenter.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -184,10 +184,17 @@ RidePresenter >> allowedFields [
"Answers the current request fields that are allowed
to be used in this presenter."

| request allowed |
request := self currentRequest.
^ self allowedFieldsFrom: self currentRequest
]

{ #category : #accessing }
RidePresenter >> allowedFieldsFrom: aRequest [
"Answers the given request fields that are allowed
to be used in this presenter."

| allowed |
allowed := self allowedParams.
^ request entity fields associationsSelect: [ :field |
^ aRequest entity fields associationsSelect: [ :field |
allowed includes: field key ]
]

Expand Down Expand Up @@ -235,15 +242,33 @@ RidePresenter >> currentSession [
^ RideCurrentSession value
]

{ #category : #actions }
RidePresenter >> ensureSessionCookie [

| response sessionCookie |
response := RideCurrentResponse value.
sessionCookie := self currentSession sessionCookie.
response headers at: 'Set-Cookie' put: sessionCookie fullString
]

{ #category : #actions }
RidePresenter >> formAction [
"Makes the receiver perform the action corresponding to a RESTful convention
and defined by the expected hidden field in its _method value.
Signals an exception if no value is found for _method
or when is found but it doesn't follow the REST convention."

| req restfulAction selector |
| req restfulAction selector unauthorized authenticityToken session |
req := self currentRequest.
unauthorized := self unauthorizedHandler.
authenticityToken := req entity
at: #authenticity_token
ifAbsent: unauthorized.
session := self currentSession.

(session authenticityTokens includesKey: authenticityToken) ifFalse:
unauthorized.

restfulAction := req entity
at: #_method
ifAbsent: [
Expand All @@ -255,12 +280,6 @@ RidePresenter >> formAction [
^ self perform: selector
]

{ #category : #accessing }
RidePresenter >> getAllDataKeysOf: aMapless [

^ aMapless maplessData keys reject: [ :e | e = '_c' or: [ e = 'id' ] ]
]

{ #category : #accessing }
RidePresenter >> getLayoutName [

Expand Down Expand Up @@ -397,7 +416,7 @@ RidePresenter >> newAuthToken [
{ #category : #actions }
RidePresenter >> onAboutToRespond [

"no-op is the default"
self ensureSessionCookie
]

{ #category : #actions }
Expand Down Expand Up @@ -521,7 +540,7 @@ RidePresenter >> renderUsing: aSelector [
{ #category : #actions }
RidePresenter >> resetSession [

Ride service invalidateSession: self currentSession
Ride service invalidateSessionId: self currentSession
]

{ #category : #accessing }
Expand Down Expand Up @@ -577,15 +596,21 @@ RidePresenter >> templateContext [
template ]
]

{ #category : #accessing }
RidePresenter >> unauthorizedHandler [
"Answers a handler to react when the auth token is missing or was not found."

^ [ RideUnauthorizedError signal: 'Authorization not found' ]
]

{ #category : #actions }
RidePresenter >> updateModelFromRequest: aRequest [
"Updates the model data following the convention of expecting for all its data keys,
parameters in the given request with their corresponding new value."

| allModelDataKeys |
allModelDataKeys := self getAllDataKeysOf: model.
allModelDataKeys do: [ :key |
| value |
value := aRequest entity at: key ifAbsent: [ nil ].
value ifNotNil: [ model at: key put: value ] ]
| allDataFields |
allDataFields := self allowedFieldsFrom: aRequest.

allDataFields keysAndValuesDo: [ :key :value |
model at: key put: value ]
]
24 changes: 14 additions & 10 deletions Ride/RideServer.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ RideServer >> setExceptionHandlers [

"First handler is to prevent further processing in case of being under maintenance."
self teapot
exception: RideMaintenanceException -> [ :ex :req |
exception: RideMaintenanceException -> [ :ex :req |
response := TeaResponse ok.
origin := req headers at: 'origin' ifAbsent: [ '*' ].
response body: self htmlMaintenancePage.
Expand All @@ -408,10 +408,10 @@ RideServer >> setExceptionHandlers [
yourself.
response ];
output: #html.

"Second for redirecting to wherever the app said it should."
self teapot
exception: RideRedirect -> [ :ex :req |
exception: RideRedirect -> [ :ex :req |
response := TeaResponse redirect.
response location: ex location.
origin := req headers at: 'origin' ifAbsent: [ '*' ].
Expand All @@ -422,11 +422,11 @@ RideServer >> setExceptionHandlers [
yourself.
response ];
output: #html.

"Hanlder for any abort exception. It answers accordingly in HTTP.
The process that signals this is expected to had loaded
the current response with the content of this response."
self teapot exception: TeaAbort -> [ :abort :req |
self teapot exception: TeaAbort -> [ :abort :req |
origin := req headers at: 'origin' ifAbsent: [ '*' ].

abort response headers
Expand All @@ -438,7 +438,7 @@ RideServer >> setExceptionHandlers [
"Hanlder for validation issues reponds with an HTTP 400.
If the signaler process wants to add details to the response it will
have done that already by using the value of RideCurrentResponse."
self teapot exception: RideValidationError -> [ :ex :req |
self teapot exception: RideValidationError -> [ :ex :req |
response := TeaResponse badRequest.
origin := req headers at: 'origin' ifAbsent: [ '*' ].
response body: (ex describeOn:
Expand All @@ -449,9 +449,13 @@ RideServer >> setExceptionHandlers [
yourself.
response ].

"Handler for request that are not properly authorized."
self teapot exception:
RideUnauthorizedError -> [ :ex :req | TeaResponse unauthorized ].

"Hanlder for request that end up signaling an unprocessable exception.
This one responds with HTTP 422 Unprocessable Content."
self teapot exception: RideUnprocessableEntity -> [ :ex :req |
self teapot exception: RideUnprocessableEntity -> [ :ex :req |
response := TeaResponse code: 422.
origin := req headers at: 'origin' ifAbsent: [ '*' ].
response body: (ex describeOn:
Expand All @@ -464,15 +468,15 @@ RideServer >> setExceptionHandlers [

"Handle the not found exception to answer an HTTP 404"
self teapot
exception: RideNotFoundError -> [ :ex :req |
exception: RideNotFoundError -> [ :ex :req |
| templateContext |
response := TeaResponse notFound.
[ ex printString ] logError.
origin := req headers at: 'origin' ifAbsent: [ '*' ].
templateContext := sharedTemplates copy
at: #status put: response code asString;
yourself.
Ride isDevelopment ifTrue: [
Ride isDevelopment ifTrue: [
templateContext
at: #error
put: { (#messageText -> ex messageText) } asDictionary ].
Expand All @@ -488,7 +492,7 @@ RideServer >> setExceptionHandlers [

"General Exception/Error handler hence anwering an HTTP 500"
self teapot
exception: Error -> [ :ex :req |
exception: Error -> [ :ex :req |
response := TeaResponse serverError.
[ ex printString ] logError.
origin := req headers at: 'origin' ifAbsent: [ '*' ].
Expand Down
Loading

0 comments on commit 786e299

Please sign in to comment.