@@ -7,9 +7,11 @@ import akka.actor.typed.Scheduler
7
7
import akka.actor.typed.javadsl.AskPattern.ask
8
8
import akka.actor.typed.javadsl.Behaviors
9
9
import blog.model.Command
10
+ import blog.model.CreateCommentRequest
10
11
import blog.model.CreateNoteRequest
11
12
import blog.model.CreateTaskRequest
12
13
import blog.model.DeleteNote
14
+ import blog.model.DeleteTask
13
15
import blog.model.LoginRequest
14
16
import blog.model.RegisterUserRequest
15
17
import blog.model.UpdateNoteRequest
@@ -34,11 +36,13 @@ import reactor.core.publisher.Mono.justOrEmpty
34
36
import reactor.kotlin.core.publisher.toFlux
35
37
import java.net.URI
36
38
import java.time.Duration
39
+ import java.util.Locale
37
40
38
41
@SpringBootApplication
39
42
class Application
40
43
41
44
fun main () {
45
+ locale()
42
46
ActorSystem .create(Server .create(), " system" )
43
47
}
44
48
@@ -59,7 +63,7 @@ fun beans(processor: ActorRef<Command>, system: ActorSystem<Void>, reader: Reade
59
63
}
60
64
61
65
fun ServerRequest.monoPathVar (s : String ): Mono <String > = justOrEmpty(s).mapNotNull { runCatching { this .pathVariable(it) }.getOrNull() }
62
- fun ServerRequest.pathAsTSID (s : String ): Mono <TSID > = this .monoPathVar(s).map { it.toLong() }.map { it. toTSID() }
66
+ fun ServerRequest.pathAsTSID (s : String ): Mono <TSID > = this .monoPathVar(s).map { it.toTSID() }
63
67
64
68
fun routes (handler : ApiHandler ): RouterFunction <ServerResponse > =
65
69
router {
@@ -73,13 +77,15 @@ fun routes(handler: ApiHandler): RouterFunction<ServerResponse> =
73
77
GET (" /note/{id}" , handler::findNote)
74
78
PUT (" /note" , handler::updateNote)
75
79
DELETE (" /note/{id}" , handler::deleteNote)
80
+ POST (" /note/{id}/comment" , handler::comment)
76
81
77
82
GET (" /users" ) { _ -> handler.findAll() }
78
83
GET (" /user/id/{id}" , handler::findById)
79
84
GET (" /user/email/{email}" , handler::findByEmail)
80
85
81
86
POST (" /tasks" , handler::createTask)
82
87
PUT (" /tasks" , handler::updateTask)
88
+ DELETE (" /tasks/{id}" , handler::deleteTask)
83
89
}
84
90
}
85
91
@@ -108,7 +114,7 @@ class ApiHandler(private val scheduler: Scheduler, private val processor: ActorR
108
114
.switchIfEmpty(forbidden)
109
115
110
116
fun findById (req : ServerRequest ): Mono <ServerResponse > = req.pathAsTSID(" id" )
111
- .flatMap { justOrEmpty(reader.findUserById (it)) }
117
+ .flatMap { justOrEmpty(reader.findUser (it)) }
112
118
.map { it.toResponse(reader) }
113
119
.flatMap { ServerResponse .ok().bodyValue(it) }
114
120
.switchIfEmpty(notFound)
@@ -122,7 +128,7 @@ class ApiHandler(private val scheduler: Scheduler, private val processor: ActorR
122
128
fun findAll (): Mono <ServerResponse > = ok.contentType(MediaType .APPLICATION_JSON ).body(reader.allUsers().toFlux(), UserResponse ::class .java)
123
129
124
130
fun createNote (req : ServerRequest ): Mono <ServerResponse > = loggedin(req)
125
- .flatMap { principal -> req.bodyToMono(CreateNoteRequest ::class .java).map { it.copy(user = principal.id.toLong ()) } }
131
+ .flatMap { principal -> req.bodyToMono(CreateNoteRequest ::class .java).map { it.copy(user = principal.id.toString ()) } }
126
132
.flatMap { fromCompletionStage(ask(processor, { rt -> it.toCommand(rt) }, timeout, scheduler)) }
127
133
.flatMap {
128
134
if (it.isSuccess) {
@@ -133,7 +139,7 @@ class ApiHandler(private val scheduler: Scheduler, private val processor: ActorR
133
139
}.switchIfEmpty(unauthorized)
134
140
135
141
fun updateNote (req : ServerRequest ): Mono <ServerResponse > = loggedin(req)
136
- .flatMap { principal -> req.bodyToMono(UpdateNoteRequest ::class .java).map { it.copy(user = principal.id) } }
142
+ .flatMap { principal -> req.bodyToMono(UpdateNoteRequest ::class .java).map { it.copy(user = principal.id.toString() ) } }
137
143
.flatMap { fromCompletionStage(ask(processor, { rt -> it.toCommand(rt) }, timeout, scheduler)) }
138
144
.flatMap { if (it.isSuccess) ok.bodyValue(it.value) else badreq(it.error.message) }
139
145
.switchIfEmpty(unauthorized)
@@ -148,17 +154,34 @@ class ApiHandler(private val scheduler: Scheduler, private val processor: ActorR
148
154
fun findNote (req : ServerRequest ): Mono <ServerResponse > =
149
155
req.pathAsTSID(" id" )
150
156
.flatMap { justOrEmpty(reader.findNote(it)) }
151
- .flatMap { ok.bodyValue(it) }
157
+ .flatMap { ok.bodyValue(it.toResponse() ) }
152
158
.switchIfEmpty(notFound)
153
159
154
160
fun createTask (req : ServerRequest ): Mono <ServerResponse > = loggedin(req)
155
- .flatMap { principal -> req.bodyToMono(CreateTaskRequest ::class .java).map { it.copy(user = principal.id) } }
161
+ .flatMap { principal -> req.bodyToMono(CreateTaskRequest ::class .java).map { it.copy(user = principal.id.toString() ) } }
156
162
.flatMap { ServerResponse .unprocessableEntity().build() }
157
163
158
164
fun updateTask (req : ServerRequest ): Mono <ServerResponse > = loggedin(req)
159
- .flatMap { principal -> req.bodyToMono(UpdateTaskRequest ::class .java).map { it.copy(user = principal.id) } }
160
- .flatMap { ServerResponse .unprocessableEntity().build() }
165
+ .flatMap { principal -> req.bodyToMono(UpdateTaskRequest ::class .java).map { it.copy(user = principal.id.toString()) } }
166
+ .flatMap { fromCompletionStage(ask(processor, { rt -> it.toCommand(rt) }, timeout, scheduler)) }
167
+ .flatMap { if (it.isSuccess) ok.build() else badRequest }
168
+ .switchIfEmpty(unauthorized)
169
+
170
+ fun deleteTask (req : ServerRequest ): Mono <ServerResponse > = loggedin(req)
171
+ .zipWith(req.pathAsTSID(" id" ).mapNotNull { reader.findTask(it) })
172
+ .filter { tup -> tup?.t2?.user != null && tup.t2.user == tup.t1.id }
173
+ .flatMap { tup -> fromCompletionStage(ask(processor, { DeleteTask (tup.t1.id, it) }, timeout, scheduler)) }
174
+ .flatMap { if (it.isSuccess) ok.build() else badRequest }
175
+ .switchIfEmpty(unauthorized)
161
176
162
177
private fun loggedin (req : ServerRequest ): Mono <User > =
163
178
justOrEmpty(req.headers().firstHeader(" Authorization" )).mapNotNull { reader.loggedin(it) }
179
+
180
+ fun comment (req : ServerRequest ): Mono <ServerResponse > = loggedin(req)
181
+ .flatMap { principal -> req.bodyToMono(CreateCommentRequest ::class .java).map { it.copy(user = principal.id.toString()) } }
182
+ .flatMap { fromCompletionStage(ask(processor, { rt -> it.toCommand(rt) }, timeout, scheduler)) }
183
+ .flatMap { if (it.isSuccess) ok.build() else badRequest }
184
+ .switchIfEmpty(unauthorized)
164
185
}
186
+
187
+ fun locale (): Unit = Locale .setDefault(Locale .of(" nl" , " NL" ))
0 commit comments