Skip to content

Commit 693f3bd

Browse files
committed
fix(model-server): /history /content /diff and /repos always returned 401
1 parent 5aeb53b commit 693f3bd

File tree

4 files changed

+187
-175
lines changed

4 files changed

+187
-175
lines changed

model-server/src/main/kotlin/org/modelix/model/server/handlers/ui/ContentExplorer.kt

Lines changed: 99 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import kotlinx.html.tr
4444
import kotlinx.html.ul
4545
import kotlinx.html.unsafe
4646
import org.modelix.authorization.checkPermission
47+
import org.modelix.authorization.requiresLogin
4748
import org.modelix.model.api.BuiltinLanguages
4849
import org.modelix.model.api.INodeResolutionScope
4950
import org.modelix.model.api.ITree
@@ -69,127 +70,129 @@ class ContentExplorer(private val repoManager: IRepositoriesManager) {
6970
get("/content") {
7071
call.respondRedirect("../repos/")
7172
}
72-
get("/content/repositories/{repository}/branches/{branch}/latest") {
73-
val repository = call.parameters["repository"]
74-
val branch = call.parameters["branch"]
75-
if (repository.isNullOrEmpty()) {
76-
call.respondText("repository not found", status = HttpStatusCode.BadRequest)
77-
return@get
78-
}
79-
if (branch.isNullOrEmpty()) {
80-
call.respondText("branch not found", status = HttpStatusCode.BadRequest)
81-
return@get
82-
}
83-
call.checkPermission(ModelServerPermissionSchema.repository(repository).branch(branch).pull)
73+
requiresLogin {
74+
get("/content/repositories/{repository}/branches/{branch}/latest") {
75+
val repository = call.parameters["repository"]
76+
val branch = call.parameters["branch"]
77+
if (repository.isNullOrEmpty()) {
78+
call.respondText("repository not found", status = HttpStatusCode.BadRequest)
79+
return@get
80+
}
81+
if (branch.isNullOrEmpty()) {
82+
call.respondText("branch not found", status = HttpStatusCode.BadRequest)
83+
return@get
84+
}
85+
call.checkPermission(ModelServerPermissionSchema.repository(repository).branch(branch).pull)
8486

85-
val latestVersion = repoManager.getVersion(BranchReference(RepositoryId(repository), branch))
86-
if (latestVersion == null) {
87-
call.respondText("unable to find latest version", status = HttpStatusCode.InternalServerError)
88-
return@get
89-
} else {
90-
call.respondRedirect("../../../versions/${latestVersion.getContentHash()}/")
91-
}
92-
}
93-
get("/content/repositories/{repository}/versions/{versionHash}") {
94-
val repositoryId = call.parameters["repository"]?.let { RepositoryId(it) }
95-
if (repositoryId == null) {
96-
call.respondText("repository parameter missing", status = HttpStatusCode.BadRequest)
97-
return@get
98-
}
99-
call.checkPermission(ModelServerPermissionSchema.repository(repositoryId).objects.read)
100-
val versionHash = call.parameters["versionHash"]
101-
if (versionHash.isNullOrEmpty()) {
102-
call.respondText("version parameter missing", status = HttpStatusCode.BadRequest)
103-
return@get
87+
val latestVersion = repoManager.getVersion(BranchReference(RepositoryId(repository), branch))
88+
if (latestVersion == null) {
89+
call.respondText("unable to find latest version", status = HttpStatusCode.InternalServerError)
90+
return@get
91+
} else {
92+
call.respondRedirect("../../../versions/${latestVersion.getContentHash()}/")
93+
}
10494
}
95+
get("/content/repositories/{repository}/versions/{versionHash}") {
96+
val repositoryId = call.parameters["repository"]?.let { RepositoryId(it) }
97+
if (repositoryId == null) {
98+
call.respondText("repository parameter missing", status = HttpStatusCode.BadRequest)
99+
return@get
100+
}
101+
call.checkPermission(ModelServerPermissionSchema.repository(repositoryId).objects.read)
102+
val versionHash = call.parameters["versionHash"]
103+
if (versionHash.isNullOrEmpty()) {
104+
call.respondText("version parameter missing", status = HttpStatusCode.BadRequest)
105+
return@get
106+
}
105107

106-
// IMPORTANT Do not let `expandTo` be an arbitrary string to avoid code injection.
107-
// The value of `expandTo` is expanded into JavaScript.
108-
val expandTo = call.request.queryParameters["expandTo"]?.let {
109-
it.toLongOrNull() ?: return@get call.respondText("Invalid expandTo value. Provide a node id.", status = HttpStatusCode.BadRequest)
110-
}
108+
// IMPORTANT Do not let `expandTo` be an arbitrary string to avoid code injection.
109+
// The value of `expandTo` is expanded into JavaScript.
110+
val expandTo = call.request.queryParameters["expandTo"]?.let {
111+
it.toLongOrNull() ?: return@get call.respondText("Invalid expandTo value. Provide a node id.", status = HttpStatusCode.BadRequest)
112+
}
111113

112-
val tree = CLVersion.loadFromHash(versionHash, repoManager.getLegacyObjectStore(repositoryId)).getTree()
113-
val rootNode = PNodeAdapter(ITree.ROOT_ID, TreePointer(tree))
114+
val tree = CLVersion.loadFromHash(versionHash, repoManager.getLegacyObjectStore(repositoryId)).getTree()
115+
val rootNode = PNodeAdapter(ITree.ROOT_ID, TreePointer(tree))
114116

115-
val expandedNodes = expandTo?.let { nodeId -> getAncestorsAndSelf(nodeId, tree) }.orEmpty()
117+
val expandedNodes = expandTo?.let { nodeId -> getAncestorsAndSelf(nodeId, tree) }.orEmpty()
116118

117-
call.respondHtmlTemplate(PageWithMenuBar("repos/", "../../../../..")) {
118-
headContent {
119-
title("Content Explorer")
120-
link("../../../../../public/content-explorer.css", rel = "stylesheet")
121-
script("text/javascript", src = "../../../../../public/content-explorer.js") {}
122-
if (expandTo != null) {
123-
script("text/javascript") {
124-
unsafe {
125-
+"""
119+
call.respondHtmlTemplate(PageWithMenuBar("repos/", "../../../../..")) {
120+
headContent {
121+
title("Content Explorer")
122+
link("../../../../../public/content-explorer.css", rel = "stylesheet")
123+
script("text/javascript", src = "../../../../../public/content-explorer.js") {}
124+
if (expandTo != null) {
125+
script("text/javascript") {
126+
unsafe {
127+
+"""
126128
document.addEventListener("DOMContentLoaded", function(event) {
127129
scrollToElement('$expandTo');
128130
});
129-
""".trimIndent()
131+
""".trimIndent()
132+
}
130133
}
131134
}
132135
}
136+
bodyContent { contentPageBody(rootNode, versionHash, expandedNodes, expandTo) }
133137
}
134-
bodyContent { contentPageBody(rootNode, versionHash, expandedNodes, expandTo) }
135-
}
136-
}
137-
post("/content/repositories/{repository}/versions/{versionHash}") {
138-
val repositoryId = call.parameters["repository"]?.let { RepositoryId(it) }
139-
if (repositoryId == null) {
140-
call.respondText("repository parameter missing", status = HttpStatusCode.BadRequest)
141-
return@post
142-
}
143-
val versionHash = call.parameters["versionHash"]
144-
if (versionHash.isNullOrEmpty()) {
145-
call.respondText("version parameter missing", status = HttpStatusCode.BadRequest)
146-
return@post
147138
}
139+
post("/content/repositories/{repository}/versions/{versionHash}") {
140+
val repositoryId = call.parameters["repository"]?.let { RepositoryId(it) }
141+
if (repositoryId == null) {
142+
call.respondText("repository parameter missing", status = HttpStatusCode.BadRequest)
143+
return@post
144+
}
145+
val versionHash = call.parameters["versionHash"]
146+
if (versionHash.isNullOrEmpty()) {
147+
call.respondText("version parameter missing", status = HttpStatusCode.BadRequest)
148+
return@post
149+
}
148150

149-
call.checkPermission(ModelServerPermissionSchema.repository(repositoryId).objects.read)
151+
call.checkPermission(ModelServerPermissionSchema.repository(repositoryId).objects.read)
150152

151-
val expandedNodes = call.receive<ContentExplorerExpandedNodes>()
153+
val expandedNodes = call.receive<ContentExplorerExpandedNodes>()
152154

153-
val tree = CLVersion.loadFromHash(versionHash, stores.getLegacyObjectStore(repositoryId)).getTree()
154-
val rootNode = PNodeAdapter(ITree.ROOT_ID, TreePointer(tree))
155+
val tree = CLVersion.loadFromHash(versionHash, stores.getLegacyObjectStore(repositoryId)).getTree()
156+
val rootNode = PNodeAdapter(ITree.ROOT_ID, TreePointer(tree))
155157

156-
var expandedNodeIds = expandedNodes.expandedNodeIds
157-
if (expandedNodes.expandAll) {
158-
expandedNodeIds = expandedNodeIds + collectExpandableChildNodes(rootNode, expandedNodes.expandedNodeIds.toSet())
159-
}
158+
var expandedNodeIds = expandedNodes.expandedNodeIds
159+
if (expandedNodes.expandAll) {
160+
expandedNodeIds = expandedNodeIds + collectExpandableChildNodes(rootNode, expandedNodes.expandedNodeIds.toSet())
161+
}
160162

161-
call.respondText(
162-
buildString {
163-
appendHTML().ul("treeRoot") {
164-
nodeItem(rootNode, expandedNodeIds.toSet())
165-
}
166-
},
167-
)
168-
}
169-
get("/content/repositories/{repository}/versions/{versionHash}/{nodeId}") {
170-
val id = call.parameters["nodeId"]?.toLongOrNull()
171-
?: return@get call.respondText("node id not found", status = HttpStatusCode.NotFound)
163+
call.respondText(
164+
buildString {
165+
appendHTML().ul("treeRoot") {
166+
nodeItem(rootNode, expandedNodeIds.toSet())
167+
}
168+
},
169+
)
170+
}
171+
get("/content/repositories/{repository}/versions/{versionHash}/{nodeId}") {
172+
val id = call.parameters["nodeId"]?.toLongOrNull()
173+
?: return@get call.respondText("node id not found", status = HttpStatusCode.NotFound)
172174

173-
val versionHash = call.parameters["versionHash"]
174-
?: return@get call.respondText("version hash not found", status = HttpStatusCode.NotFound)
175+
val versionHash = call.parameters["versionHash"]
176+
?: return@get call.respondText("version hash not found", status = HttpStatusCode.NotFound)
175177

176-
val repositoryId = call.parameters["repository"]
177-
?: return@get call.respondText("repository parameter missing", status = HttpStatusCode.BadRequest)
178+
val repositoryId = call.parameters["repository"]
179+
?: return@get call.respondText("repository parameter missing", status = HttpStatusCode.BadRequest)
178180

179-
call.checkPermission(ModelServerPermissionSchema.repository(repositoryId).objects.read)
181+
call.checkPermission(ModelServerPermissionSchema.repository(repositoryId).objects.read)
180182

181-
val version = try {
182-
CLVersion.loadFromHash(versionHash, stores.getLegacyObjectStore(RepositoryId(repositoryId)))
183-
} catch (ex: RuntimeException) {
184-
return@get call.respondText("version not found", status = HttpStatusCode.NotFound)
185-
}
183+
val version = try {
184+
CLVersion.loadFromHash(versionHash, stores.getLegacyObjectStore(RepositoryId(repositoryId)))
185+
} catch (ex: RuntimeException) {
186+
return@get call.respondText("version not found", status = HttpStatusCode.NotFound)
187+
}
186188

187-
val node = PNodeAdapter(id, TreePointer(version.getTree())).takeIf { it.isValid }
189+
val node = PNodeAdapter(id, TreePointer(version.getTree())).takeIf { it.isValid }
188190

189-
if (node != null) {
190-
call.respondHtml { body { nodeInspector(node) } }
191-
} else {
192-
call.respondText("node id not found", status = HttpStatusCode.NotFound)
191+
if (node != null) {
192+
call.respondHtml { body { nodeInspector(node) } }
193+
} else {
194+
call.respondText("node id not found", status = HttpStatusCode.NotFound)
195+
}
193196
}
194197
}
195198
}

model-server/src/main/kotlin/org/modelix/model/server/handlers/ui/DiffView.kt

Lines changed: 41 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import kotlinx.html.thead
3232
import kotlinx.html.tr
3333
import org.modelix.authorization.checkPermission
3434
import org.modelix.authorization.hasPermission
35+
import org.modelix.authorization.requiresLogin
3536
import org.modelix.model.api.BuiltinLanguages
3637
import org.modelix.model.api.ITreeChangeVisitorEx
3738
import org.modelix.model.lazy.CLTree
@@ -67,48 +68,50 @@ class DiffView(private val repositoryManager: RepositoriesManager) {
6768
*/
6869
fun init(application: Application) {
6970
application.routing {
70-
get("/diff") {
71-
val visibleRepositories = repositoryManager.getRepositories().filter {
72-
call.hasPermission(ModelServerPermissionSchema.repository(it).list)
73-
}
74-
call.respondHtmlTemplate(PageWithMenuBar("diff", "..")) {
75-
bodyContent {
76-
buildDiffInputPage(visibleRepositories)
71+
requiresLogin {
72+
get("/diff") {
73+
val visibleRepositories = repositoryManager.getRepositories().filter {
74+
call.hasPermission(ModelServerPermissionSchema.repository(it).list)
75+
}
76+
call.respondHtmlTemplate(PageWithMenuBar("diff", "..")) {
77+
bodyContent {
78+
buildDiffInputPage(visibleRepositories)
79+
}
7780
}
7881
}
79-
}
80-
get("/diff/view") {
81-
val repoId =
82-
(call.request.queryParameters["repository"])?.let { param -> RepositoryId(param) } ?: throw HttpException(
82+
get("/diff/view") {
83+
val repoId =
84+
(call.request.queryParameters["repository"])?.let { param -> RepositoryId(param) } ?: throw HttpException(
85+
HttpStatusCode.BadRequest,
86+
"missing repository",
87+
)
88+
call.checkPermission(ModelServerPermissionSchema.repository(repoId).objects.read)
89+
90+
val oldVersionHash = call.request.queryParameters["oldVersionHash"] ?: throw HttpException(
91+
HttpStatusCode.BadRequest,
92+
"missing oldVersionHash",
93+
)
94+
val newVersionHash = call.request.queryParameters["newVersionHash"] ?: throw HttpException(
8395
HttpStatusCode.BadRequest,
84-
"missing repository",
96+
"missing newVersionHash",
97+
)
98+
99+
val sizeLimit = call.request.queryParameters["sizeLimit"]?.let { param ->
100+
param.toIntOrNull() ?: throw HttpException(HttpStatusCode.BadRequest, "invalid sizeLimit")
101+
} ?: DEFAULT_SIZE_LIMIT
102+
103+
val oldVersion = repositoryManager.getVersion(repoId, oldVersionHash) ?: throw VersionNotFoundException(
104+
oldVersionHash,
85105
)
86-
call.checkPermission(ModelServerPermissionSchema.repository(repoId).objects.read)
87-
88-
val oldVersionHash = call.request.queryParameters["oldVersionHash"] ?: throw HttpException(
89-
HttpStatusCode.BadRequest,
90-
"missing oldVersionHash",
91-
)
92-
val newVersionHash = call.request.queryParameters["newVersionHash"] ?: throw HttpException(
93-
HttpStatusCode.BadRequest,
94-
"missing newVersionHash",
95-
)
96-
97-
val sizeLimit = call.request.queryParameters["sizeLimit"]?.let { param ->
98-
param.toIntOrNull() ?: throw HttpException(HttpStatusCode.BadRequest, "invalid sizeLimit")
99-
} ?: DEFAULT_SIZE_LIMIT
100-
101-
val oldVersion = repositoryManager.getVersion(repoId, oldVersionHash) ?: throw VersionNotFoundException(
102-
oldVersionHash,
103-
)
104-
val newVersion = repositoryManager.getVersion(repoId, newVersionHash) ?: throw VersionNotFoundException(
105-
newVersionHash,
106-
)
107-
108-
val diff = calculateDiff(oldVersion, newVersion, sizeLimit)
109-
call.respondHtmlTemplate(PageWithMenuBar("diff", baseUrl)) {
110-
bodyContent {
111-
buildDiffView(diff, oldVersionHash, newVersionHash, repoId.id, sizeLimit)
106+
val newVersion = repositoryManager.getVersion(repoId, newVersionHash) ?: throw VersionNotFoundException(
107+
newVersionHash,
108+
)
109+
110+
val diff = calculateDiff(oldVersion, newVersion, sizeLimit)
111+
call.respondHtmlTemplate(PageWithMenuBar("diff", baseUrl)) {
112+
bodyContent {
113+
buildDiffView(diff, oldVersionHash, newVersionHash, repoId.id, sizeLimit)
114+
}
112115
}
113116
}
114117
}

0 commit comments

Comments
 (0)