Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
haskell-gargantext
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
147
Issues
147
List
Board
Labels
Milestones
Merge Requests
5
Merge Requests
5
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
gargantext
haskell-gargantext
Commits
3763d0dc
Commit
3763d0dc
authored
Nov 06, 2023
by
Alfredo Di Napoli
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Complete NodeError -> FrontendError
parent
37c94f6c
Pipeline
#5330
passed with stages
in 71 minutes and 54 seconds
Changes
15
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
504 additions
and
273 deletions
+504
-273
Main.hs
bin/gargantext-admin/Main.hs
+2
-1
Main.hs
bin/gargantext-init/Main.hs
+2
-1
Errors.hs
src/Gargantext/API/Errors.hs
+42
-34
Types.hs
src/Gargantext/API/Errors/Types.hs
+327
-133
Backend.hs
src/Gargantext/API/Errors/Types/Backend.hs
+23
-13
Share.hs
src/Gargantext/API/Node/Share.hs
+2
-2
Individu.hs
src/Gargantext/Core/Types/Individu.hs
+1
-2
Node.hs
src/Gargantext/Database/Action/Node.hs
+17
-22
User.hs
src/Gargantext/Database/Action/User.hs
+9
-11
New.hs
src/Gargantext/Database/Action/User/New.hs
+11
-12
Node.hs
src/Gargantext/Database/Admin/Types/Node.hs
+3
-0
Node.hs
src/Gargantext/Database/Query/Table/Node.hs
+17
-13
Error.hs
src/Gargantext/Database/Query/Table/Node/Error.hs
+38
-20
User.hs
src/Gargantext/Database/Query/Table/User.hs
+6
-4
Root.hs
src/Gargantext/Database/Query/Tree/Root.hs
+4
-5
No files found.
bin/gargantext-admin/Main.hs
View file @
3763d0dc
...
@@ -22,12 +22,13 @@ import Gargantext.Database.Admin.Types.Node
...
@@ -22,12 +22,13 @@ import Gargantext.Database.Admin.Types.Node
import
Gargantext.Database.Prelude
(
Cmd
''
)
import
Gargantext.Database.Prelude
(
Cmd
''
)
import
Gargantext.Prelude
import
Gargantext.Prelude
import
Gargantext.API.Admin.EnvTypes
(
DevEnv
)
import
Gargantext.API.Admin.EnvTypes
(
DevEnv
)
import
qualified
Data.List.NonEmpty
as
NE
main
::
IO
()
main
::
IO
()
main
=
do
main
=
do
(
iniPath
:
mails
)
<-
getArgs
(
iniPath
:
mails
)
<-
getArgs
withDevEnv
iniPath
$
\
env
->
do
withDevEnv
iniPath
$
\
env
->
do
x
<-
runCmdDev
env
((
newUsers
$
map
cs
mails
)
::
Cmd''
DevEnv
BackendInternalError
[
UserId
]
)
x
<-
runCmdDev
env
((
newUsers
$
NE
.
map
cs
(
NE
.
fromList
mails
))
::
Cmd''
DevEnv
BackendInternalError
(
NonEmpty
UserId
)
)
putStrLn
(
show
x
::
Text
)
putStrLn
(
show
x
::
Text
)
pure
()
pure
()
bin/gargantext-init/Main.hs
View file @
3763d0dc
...
@@ -29,6 +29,7 @@ import Gargantext.Database.Query.Table.Node (getOrMkList)
...
@@ -29,6 +29,7 @@ import Gargantext.Database.Query.Table.Node (getOrMkList)
import
Gargantext.Database.Query.Table.User
(
insertNewUsers
,
)
import
Gargantext.Database.Query.Table.User
(
insertNewUsers
,
)
import
Gargantext.Prelude
import
Gargantext.Prelude
import
Gargantext.Prelude.Config
(
GargConfig
(
..
),
readConfig
)
import
Gargantext.Prelude.Config
(
GargConfig
(
..
),
readConfig
)
import
qualified
Data.List.NonEmpty
as
NE
main
::
IO
()
main
::
IO
()
...
@@ -50,7 +51,7 @@ main = do
...
@@ -50,7 +51,7 @@ main = do
let
createUsers
::
Cmd
BackendInternalError
Int64
let
createUsers
::
Cmd
BackendInternalError
Int64
createUsers
=
insertNewUsers
(
NewUser
"gargantua"
(
cs
email
)
(
GargPassword
$
cs
password
)
createUsers
=
insertNewUsers
(
NewUser
"gargantua"
(
cs
email
)
(
GargPassword
$
cs
password
)
:
arbitraryNewUsers
NE
.:|
arbitraryNewUsers
)
)
let
let
...
...
src/Gargantext/API/Errors.hs
View file @
3763d0dc
...
@@ -62,60 +62,68 @@ internalServerErrorToFrontendError = \case
...
@@ -62,60 +62,68 @@ internalServerErrorToFrontendError = \case
jobErrorToFrontendError
::
JobError
->
FrontendError
jobErrorToFrontendError
::
JobError
->
FrontendError
jobErrorToFrontendError
=
\
case
jobErrorToFrontendError
=
\
case
InvalidIDType
idTy
->
mkFrontendErrNoDiagnostic
$
FE_job_
error_
invalid_id_type
idTy
InvalidIDType
idTy
->
mkFrontendErrNoDiagnostic
$
FE_job_invalid_id_type
idTy
IDExpired
jobId
->
mkFrontendErrNoDiagnostic
$
FE_job_e
rror_e
xpired
jobId
IDExpired
jobId
->
mkFrontendErrNoDiagnostic
$
FE_job_expired
jobId
InvalidMacID
macId
->
mkFrontendErrNoDiagnostic
$
FE_job_
error_
invalid_mac
macId
InvalidMacID
macId
->
mkFrontendErrNoDiagnostic
$
FE_job_invalid_mac
macId
UnknownJob
jobId
->
mkFrontendErrNoDiagnostic
$
FE_job_
error_
unknown_job
jobId
UnknownJob
jobId
->
mkFrontendErrNoDiagnostic
$
FE_job_unknown_job
jobId
JobException
err
->
mkFrontendErrNoDiagnostic
$
FE_job_
error_
generic_exception
(
T
.
pack
$
displayException
err
)
JobException
err
->
mkFrontendErrNoDiagnostic
$
FE_job_generic_exception
(
T
.
pack
$
displayException
err
)
authErrorToFrontendError
::
AuthenticationError
->
FrontendError
authErrorToFrontendError
::
AuthenticationError
->
FrontendError
authErrorToFrontendError
=
\
case
authErrorToFrontendError
=
\
case
-- For now, we ignore the Jose error, as they are too specific
-- For now, we ignore the Jose error, as they are too specific
-- (i.e. they should be logged internally to Sentry rather than shared
-- (i.e. they should be logged internally to Sentry rather than shared
-- externall).
-- externall
y
).
LoginFailed
nid
uid
_
LoginFailed
nid
uid
_
->
mkFrontendErr'
"Invalid username/password, or invalid session token."
$
FE_login_failed_error
nid
uid
->
mkFrontendErr'
"Invalid username/password, or invalid session token."
$
FE_login_failed_error
nid
uid
nodeErrorToFrontendError
::
NodeError
->
FrontendError
nodeErrorToFrontendError
::
NodeError
->
FrontendError
nodeErrorToFrontendError
ne
=
case
ne
of
nodeErrorToFrontendError
ne
=
case
ne
of
NoListFound
lid
NoListFound
lid
->
mkFrontendErrShow
$
FE_node_
error_
list_not_found
lid
->
mkFrontendErrShow
$
FE_node_list_not_found
lid
NoRootFound
NoRootFound
->
mkFrontendErrShow
FE_node_
error_
root_not_found
->
mkFrontendErrShow
FE_node_root_not_found
NoCorpusFound
NoCorpusFound
->
mkFrontendErrShow
FE_node_
error_
corpus_not_found
->
mkFrontendErrShow
FE_node_corpus_not_found
NoUserFound
_ur
NoUserFound
_ur
->
undefined
->
undefined
MkNode
NodeCreationFailed
reason
->
undefined
->
case
reason
of
UserNoParent
UserParentAlreadyExists
pId
uId
->
undefined
->
mkFrontendErrShow
$
FE_node_creation_failed_parent_exists
uId
pId
HasParent
UserParentDoesNotExist
uId
->
undefined
->
mkFrontendErrShow
$
FE_node_creation_failed_no_parent
uId
ManyParents
InsertNodeFailed
uId
pId
->
undefined
->
mkFrontendErrShow
$
FE_node_creation_failed_insert_node
uId
pId
NegativeId
UserHasNegativeId
uid
->
undefined
->
mkFrontendErrShow
$
FE_node_creation_failed_user_negative_id
uid
NodeLookupFailed
reason
->
case
reason
of
NodeDoesNotExist
nid
->
mkFrontendErrShow
$
FE_node_lookup_failed_not_found
nid
UserDoesNotExist
uid
->
mkFrontendErrShow
$
FE_node_lookup_failed_user_not_found
uid
UserNameDoesNotExist
uname
->
mkFrontendErrShow
$
FE_node_lookup_failed_username_not_found
uname
UserHasTooManyRoots
uid
roots
->
mkFrontendErrShow
$
FE_node_lookup_failed_user_too_many_roots
uid
roots
NotImplYet
NotImplYet
->
mkFrontendErrShow
FE_node_error_not_implemented_yet
->
mkFrontendErrShow
FE_node_not_implemented_yet
ManyNodeUsers
NoContextFound
contextId
->
undefined
->
mkFrontendErrShow
$
FE_node_context_not_found
contextId
DoesNotExist
nodeId
->
mkFrontendErrShow
$
FE_node_error_not_found
nodeId
NoContextFound
_contextId
->
undefined
NeedsConfiguration
NeedsConfiguration
->
undefined
->
mkFrontendErrShow
$
FE_node_needs_configuration
NodeError
_txt
NodeError
err
->
undefined
->
mkFrontendErrShow
$
FE_node_generic_exception
(
T
.
pack
$
displayException
err
)
QueryNoParse
_txt
->
undefined
-- backward-compatibility shims, to remove eventually.
DoesNotExist
nid
->
mkFrontendErrShow
$
FE_node_lookup_failed_not_found
nid
treeErrorToFrontendError
::
TreeError
->
FrontendError
treeErrorToFrontendError
::
TreeError
->
FrontendError
treeErrorToFrontendError
te
=
case
te
of
treeErrorToFrontendError
te
=
case
te
of
NoRoot
->
mkFrontendErrShow
FE_tree_
error_
root_not_found
NoRoot
->
mkFrontendErrShow
FE_tree_root_not_found
EmptyRoot
->
mkFrontendErrShow
FE_tree_e
rror_e
mpty_root
EmptyRoot
->
mkFrontendErrShow
FE_tree_empty_root
TooManyRoots
roots
->
mkFrontendErrShow
$
FE_tree_
error_
too_many_roots
roots
TooManyRoots
roots
->
mkFrontendErrShow
$
FE_tree_too_many_roots
roots
-- | Converts a 'FrontendError' into a 'ServerError' that the servant app can
-- | Converts a 'FrontendError' into a 'ServerError' that the servant app can
-- return to the frontend.
-- return to the frontend.
...
...
src/Gargantext/API/Errors/Types.hs
View file @
3763d0dc
...
@@ -68,6 +68,7 @@ import Text.Read (readMaybe)
...
@@ -68,6 +68,7 @@ import Text.Read (readMaybe)
import
qualified
Data.List.NonEmpty
as
NE
import
qualified
Data.List.NonEmpty
as
NE
import
Data.Maybe
import
Data.Maybe
import
Gargantext.API.Admin.Auth.Types
(
AuthenticationError
)
import
Gargantext.API.Admin.Auth.Types
(
AuthenticationError
)
import
Gargantext.Core.Types.Individu
-- | A 'WithStacktrace' carries an error alongside its
-- | A 'WithStacktrace' carries an error alongside its
-- 'CallStack', to be able to print the correct source location
-- 'CallStack', to be able to print the correct source location
...
@@ -171,26 +172,73 @@ $(deriveIsFrontendErrorData ''BackendErrorCode)
...
@@ -171,26 +172,73 @@ $(deriveIsFrontendErrorData ''BackendErrorCode)
data
NoFrontendErrorData
=
NoFrontendErrorData
data
NoFrontendErrorData
=
NoFrontendErrorData
newtype
instance
ToFrontendErrorData
'E
C
_404__node_
error_
list_not_found
=
newtype
instance
ToFrontendErrorData
'E
C
_404__node_list_not_found
=
FE_node_
error_
list_not_found
{
lnf_list_id
::
ListId
}
FE_node_list_not_found
{
lnf_list_id
::
ListId
}
deriving
(
Show
,
Eq
,
Generic
)
deriving
(
Show
,
Eq
,
Generic
)
data
instance
ToFrontendErrorData
'E
C
_404__node_
error_
root_not_found
=
data
instance
ToFrontendErrorData
'E
C
_404__node_root_not_found
=
FE_node_
error_
root_not_found
FE_node_root_not_found
deriving
(
Show
,
Eq
,
Generic
)
deriving
(
Show
,
Eq
,
Generic
)
data
instance
ToFrontendErrorData
'E
C
_404__node_
error_
corpus_not_found
=
data
instance
ToFrontendErrorData
'E
C
_404__node_corpus_not_found
=
FE_node_
error_
corpus_not_found
FE_node_corpus_not_found
deriving
(
Show
,
Eq
,
Generic
)
deriving
(
Show
,
Eq
,
Generic
)
data
instance
ToFrontendErrorData
'E
C
_500__node_
error_
not_implemented_yet
=
data
instance
ToFrontendErrorData
'E
C
_500__node_not_implemented_yet
=
FE_node_
error_
not_implemented_yet
FE_node_not_implemented_yet
deriving
(
Show
,
Eq
,
Generic
)
deriving
(
Show
,
Eq
,
Generic
)
data
instance
ToFrontendErrorData
'E
C
_404__node_error
_not_found
=
newtype
instance
ToFrontendErrorData
'E
C
_404__node_lookup_failed
_not_found
=
FE_node_
error_not_found
{
nenf_node_id
::
!
NodeId
}
FE_node_
lookup_failed_not_found
{
nenf_node_id
::
NodeId
}
deriving
(
Show
,
Eq
,
Generic
)
deriving
(
Show
,
Eq
,
Generic
)
newtype
instance
ToFrontendErrorData
'E
C
_404__node_lookup_failed_user_not_found
=
FE_node_lookup_failed_user_not_found
{
nenf_user_id
::
UserId
}
deriving
(
Show
,
Eq
,
Generic
)
newtype
instance
ToFrontendErrorData
'E
C
_404__node_lookup_failed_username_not_found
=
FE_node_lookup_failed_username_not_found
{
nenf_username
::
Username
}
deriving
(
Show
,
Eq
,
Generic
)
newtype
instance
ToFrontendErrorData
'E
C
_400__node_creation_failed_user_negative_id
=
FE_node_creation_failed_user_negative_id
{
neuni_user_id
::
UserId
}
deriving
(
Show
,
Eq
,
Generic
)
data
instance
ToFrontendErrorData
'E
C
_400__node_lookup_failed_user_too_many_roots
=
FE_node_lookup_failed_user_too_many_roots
{
netmr_user_id
::
UserId
,
netmr_roots
::
[
NodeId
]
}
deriving
(
Show
,
Eq
,
Generic
)
newtype
instance
ToFrontendErrorData
'E
C
_404__node_context_not_found
=
FE_node_context_not_found
{
necnf_context_id
::
ContextId
}
deriving
(
Show
,
Eq
,
Generic
)
data
instance
ToFrontendErrorData
'E
C
_400__node_creation_failed_parent_exists
=
FE_node_creation_failed_parent_exists
{
necpe_parent_id
::
ParentId
,
necpe_user_id
::
UserId
}
deriving
(
Show
,
Eq
,
Generic
)
newtype
instance
ToFrontendErrorData
'E
C
_400__node_creation_failed_no_parent
=
FE_node_creation_failed_no_parent
{
necnp_user_id
::
UserId
}
deriving
(
Show
,
Eq
,
Generic
)
data
instance
ToFrontendErrorData
'E
C
_400__node_creation_failed_insert_node
=
FE_node_creation_failed_insert_node
{
necin_user_id
::
UserId
,
necin_parent_id
::
ParentId
}
deriving
(
Show
,
Eq
,
Generic
)
newtype
instance
ToFrontendErrorData
'E
C
_500__node_generic_exception
=
FE_node_generic_exception
{
nege_error
::
T
.
Text
}
deriving
(
Show
,
Eq
,
Generic
)
data
instance
ToFrontendErrorData
'E
C
_400__node_needs_configuration
=
FE_node_needs_configuration
deriving
(
Show
,
Eq
,
Generic
)
--
--
-- validation errors
-- validation errors
--
--
...
@@ -214,44 +262,44 @@ data instance ToFrontendErrorData 'EC_403__login_failed_error =
...
@@ -214,44 +262,44 @@ data instance ToFrontendErrorData 'EC_403__login_failed_error =
-- Tree errors
-- Tree errors
--
--
data
instance
ToFrontendErrorData
'E
C
_404__tree_
error_
root_not_found
=
data
instance
ToFrontendErrorData
'E
C
_404__tree_root_not_found
=
FE_tree_
error_
root_not_found
FE_tree_root_not_found
deriving
(
Show
,
Eq
,
Generic
)
deriving
(
Show
,
Eq
,
Generic
)
data
instance
ToFrontendErrorData
'E
C
_404__tree_e
rror_e
mpty_root
=
data
instance
ToFrontendErrorData
'E
C
_404__tree_empty_root
=
FE_tree_e
rror_e
mpty_root
FE_tree_empty_root
deriving
(
Show
,
Eq
,
Generic
)
deriving
(
Show
,
Eq
,
Generic
)
data
instance
ToFrontendErrorData
'E
C
_500__tree_
error_
too_many_roots
=
data
instance
ToFrontendErrorData
'E
C
_500__tree_too_many_roots
=
FE_tree_
error_
too_many_roots
{
tmr_roots
::
NonEmpty
NodeId
}
FE_tree_too_many_roots
{
tmr_roots
::
NonEmpty
NodeId
}
deriving
(
Show
,
Eq
,
Generic
)
deriving
(
Show
,
Eq
,
Generic
)
--
--
-- Job errors
-- Job errors
--
--
data
instance
ToFrontendErrorData
'E
C
_500__job_
error_
invalid_id_type
=
data
instance
ToFrontendErrorData
'E
C
_500__job_invalid_id_type
=
FE_job_
error_
invalid_id_type
{
jeiit_type
::
T
.
Text
}
FE_job_invalid_id_type
{
jeiit_type
::
T
.
Text
}
deriving
(
Show
,
Eq
,
Generic
)
deriving
(
Show
,
Eq
,
Generic
)
data
instance
ToFrontendErrorData
'E
C
_500__job_e
rror_e
xpired
=
data
instance
ToFrontendErrorData
'E
C
_500__job_expired
=
FE_job_e
rror_e
xpired
{
jee_job_id
::
Int
}
FE_job_expired
{
jee_job_id
::
Int
}
deriving
(
Show
,
Eq
,
Generic
)
deriving
(
Show
,
Eq
,
Generic
)
data
instance
ToFrontendErrorData
'E
C
_500__job_
error_
invalid_mac
=
data
instance
ToFrontendErrorData
'E
C
_500__job_invalid_mac
=
FE_job_
error_
invalid_mac
{
jeim_mac
::
T
.
Text
}
FE_job_invalid_mac
{
jeim_mac
::
T
.
Text
}
deriving
(
Show
,
Eq
,
Generic
)
deriving
(
Show
,
Eq
,
Generic
)
data
instance
ToFrontendErrorData
'E
C
_500__job_
error_
unknown_job
=
data
instance
ToFrontendErrorData
'E
C
_500__job_unknown_job
=
FE_job_
error_
unknown_job
{
jeuj_job_id
::
Int
}
FE_job_unknown_job
{
jeuj_job_id
::
Int
}
deriving
(
Show
,
Eq
,
Generic
)
deriving
(
Show
,
Eq
,
Generic
)
data
instance
ToFrontendErrorData
'E
C
_500__internal_server_error
=
data
instance
ToFrontendErrorData
'E
C
_500__internal_server_error
=
FE_internal_server_error
{
ise_error
::
T
.
Text
}
FE_internal_server_error
{
ise_error
::
T
.
Text
}
deriving
(
Show
,
Eq
,
Generic
)
deriving
(
Show
,
Eq
,
Generic
)
data
instance
ToFrontendErrorData
'E
C
_500__job_
error_
generic_exception
=
data
instance
ToFrontendErrorData
'E
C
_500__job_generic_exception
=
FE_job_
error_
generic_exception
{
jege_error
::
T
.
Text
}
FE_job_generic_exception
{
jege_error
::
T
.
Text
}
deriving
(
Show
,
Eq
,
Generic
)
deriving
(
Show
,
Eq
,
Generic
)
----------------------------------------------------------------------------
----------------------------------------------------------------------------
...
@@ -260,40 +308,125 @@ data instance ToFrontendErrorData 'EC_500__job_error_generic_exception =
...
@@ -260,40 +308,125 @@ data instance ToFrontendErrorData 'EC_500__job_error_generic_exception =
-- payload, we can render it to JSON and parse it back.
-- payload, we can render it to JSON and parse it back.
----------------------------------------------------------------------------
----------------------------------------------------------------------------
instance
ToJSON
(
ToFrontendErrorData
'E
C
_404__node_
error_
list_not_found
)
where
instance
ToJSON
(
ToFrontendErrorData
'E
C
_404__node_list_not_found
)
where
toJSON
(
FE_node_
error_
list_not_found
lid
)
=
toJSON
(
FE_node_list_not_found
lid
)
=
JSON
.
object
[
"list_id"
.=
toJSON
lid
]
JSON
.
object
[
"list_id"
.=
toJSON
lid
]
instance
FromJSON
(
ToFrontendErrorData
'E
C
_404__node_
error_
list_not_found
)
where
instance
FromJSON
(
ToFrontendErrorData
'E
C
_404__node_list_not_found
)
where
parseJSON
=
withObject
"FE_node_
error_
list_not_found"
$
\
o
->
do
parseJSON
=
withObject
"FE_node_list_not_found"
$
\
o
->
do
lnf_list_id
<-
o
.:
"list_id"
lnf_list_id
<-
o
.:
"list_id"
pure
FE_node_
error_
list_not_found
{
..
}
pure
FE_node_list_not_found
{
..
}
instance
ToJSON
(
ToFrontendErrorData
'E
C
_404__node_
error_
root_not_found
)
where
instance
ToJSON
(
ToFrontendErrorData
'E
C
_404__node_root_not_found
)
where
toJSON
_
=
JSON
.
Null
toJSON
_
=
JSON
.
Null
instance
FromJSON
(
ToFrontendErrorData
'E
C
_404__node_
error_
root_not_found
)
where
instance
FromJSON
(
ToFrontendErrorData
'E
C
_404__node_root_not_found
)
where
parseJSON
_
=
pure
FE_node_
error_
root_not_found
parseJSON
_
=
pure
FE_node_root_not_found
instance
ToJSON
(
ToFrontendErrorData
'E
C
_404__node_
error_
corpus_not_found
)
where
instance
ToJSON
(
ToFrontendErrorData
'E
C
_404__node_corpus_not_found
)
where
toJSON
_
=
JSON
.
Null
toJSON
_
=
JSON
.
Null
instance
FromJSON
(
ToFrontendErrorData
'E
C
_404__node_
error_
corpus_not_found
)
where
instance
FromJSON
(
ToFrontendErrorData
'E
C
_404__node_corpus_not_found
)
where
parseJSON
_
=
pure
FE_node_
error_
corpus_not_found
parseJSON
_
=
pure
FE_node_corpus_not_found
instance
ToJSON
(
ToFrontendErrorData
'E
C
_500__node_
error_
not_implemented_yet
)
where
instance
ToJSON
(
ToFrontendErrorData
'E
C
_500__node_not_implemented_yet
)
where
toJSON
_
=
JSON
.
Null
toJSON
_
=
JSON
.
Null
instance
FromJSON
(
ToFrontendErrorData
'E
C
_500__node_
error_
not_implemented_yet
)
where
instance
FromJSON
(
ToFrontendErrorData
'E
C
_500__node_not_implemented_yet
)
where
parseJSON
_
=
pure
FE_node_
error_
not_implemented_yet
parseJSON
_
=
pure
FE_node_not_implemented_yet
instance
ToJSON
(
ToFrontendErrorData
'E
C
_404__node_
error
_not_found
)
where
instance
ToJSON
(
ToFrontendErrorData
'E
C
_404__node_
lookup_failed
_not_found
)
where
toJSON
(
FE_node_
error
_not_found
nodeId
)
=
object
[
"node_id"
.=
toJSON
nodeId
]
toJSON
(
FE_node_
lookup_failed
_not_found
nodeId
)
=
object
[
"node_id"
.=
toJSON
nodeId
]
instance
FromJSON
(
ToFrontendErrorData
'E
C
_404__node_
error
_not_found
)
where
instance
FromJSON
(
ToFrontendErrorData
'E
C
_404__node_
lookup_failed
_not_found
)
where
parseJSON
=
withObject
"FE_node_
error
_not_found"
$
\
o
->
do
parseJSON
=
withObject
"FE_node_
lookup_failed
_not_found"
$
\
o
->
do
nenf_node_id
<-
o
.:
"node_id"
nenf_node_id
<-
o
.:
"node_id"
pure
FE_node_error_not_found
{
..
}
pure
FE_node_lookup_failed_not_found
{
..
}
instance
ToJSON
(
ToFrontendErrorData
'E
C
_404__node_lookup_failed_user_not_found
)
where
toJSON
(
FE_node_lookup_failed_user_not_found
userId
)
=
object
[
"user_id"
.=
toJSON
userId
]
instance
FromJSON
(
ToFrontendErrorData
'E
C
_404__node_lookup_failed_user_not_found
)
where
parseJSON
=
withObject
"FE_node_lookup_failed_user_not_found"
$
\
o
->
do
nenf_user_id
<-
o
.:
"user_id"
pure
FE_node_lookup_failed_user_not_found
{
..
}
instance
ToJSON
(
ToFrontendErrorData
'E
C
_404__node_lookup_failed_username_not_found
)
where
toJSON
(
FE_node_lookup_failed_username_not_found
username
)
=
object
[
"username"
.=
toJSON
username
]
instance
FromJSON
(
ToFrontendErrorData
'E
C
_404__node_lookup_failed_username_not_found
)
where
parseJSON
=
withObject
"FE_node_lookup_failed_username_not_found"
$
\
o
->
do
nenf_username
<-
o
.:
"username"
pure
FE_node_lookup_failed_username_not_found
{
..
}
instance
ToJSON
(
ToFrontendErrorData
'E
C
_400__node_creation_failed_user_negative_id
)
where
toJSON
(
FE_node_creation_failed_user_negative_id
userId
)
=
object
[
"user_id"
.=
toJSON
userId
]
instance
FromJSON
(
ToFrontendErrorData
'E
C
_400__node_creation_failed_user_negative_id
)
where
parseJSON
=
withObject
"FE_node_creation_failed_user_negative_id"
$
\
o
->
do
neuni_user_id
<-
o
.:
"user_id"
pure
FE_node_creation_failed_user_negative_id
{
..
}
instance
ToJSON
(
ToFrontendErrorData
'E
C
_400__node_lookup_failed_user_too_many_roots
)
where
toJSON
(
FE_node_lookup_failed_user_too_many_roots
userId
roots
)
=
object
[
"user_id"
.=
toJSON
userId
,
"roots"
.=
toJSON
roots
]
instance
FromJSON
(
ToFrontendErrorData
'E
C
_400__node_lookup_failed_user_too_many_roots
)
where
parseJSON
=
withObject
"FE_node_lookup_failed_user_too_many_roots"
$
\
o
->
do
netmr_user_id
<-
o
.:
"user_id"
netmr_roots
<-
o
.:
"roots"
pure
FE_node_lookup_failed_user_too_many_roots
{
..
}
instance
ToJSON
(
ToFrontendErrorData
'E
C
_404__node_context_not_found
)
where
toJSON
(
FE_node_context_not_found
cId
)
=
object
[
"context_id"
.=
toJSON
cId
]
instance
FromJSON
(
ToFrontendErrorData
'E
C
_404__node_context_not_found
)
where
parseJSON
=
withObject
"FE_node_context_not_found"
$
\
o
->
do
necnf_context_id
<-
o
.:
"context_id"
pure
FE_node_context_not_found
{
..
}
instance
ToJSON
(
ToFrontendErrorData
'E
C
_400__node_creation_failed_no_parent
)
where
toJSON
(
FE_node_creation_failed_no_parent
uId
)
=
object
[
"user_id"
.=
toJSON
uId
]
instance
FromJSON
(
ToFrontendErrorData
'E
C
_400__node_creation_failed_no_parent
)
where
parseJSON
=
withObject
"FE_node_creation_failed_no_parent"
$
\
o
->
do
necnp_user_id
<-
o
.:
"user_id"
pure
FE_node_creation_failed_no_parent
{
..
}
instance
ToJSON
(
ToFrontendErrorData
'E
C
_400__node_creation_failed_parent_exists
)
where
toJSON
FE_node_creation_failed_parent_exists
{
..
}
=
object
[
"user_id"
.=
toJSON
necpe_user_id
,
"parent_id"
.=
toJSON
necpe_parent_id
]
instance
FromJSON
(
ToFrontendErrorData
'E
C
_400__node_creation_failed_parent_exists
)
where
parseJSON
=
withObject
"FE_node_creation_failed_parent_exists"
$
\
o
->
do
necpe_user_id
<-
o
.:
"user_id"
necpe_parent_id
<-
o
.:
"parent_id"
pure
FE_node_creation_failed_parent_exists
{
..
}
instance
ToJSON
(
ToFrontendErrorData
'E
C
_400__node_creation_failed_insert_node
)
where
toJSON
FE_node_creation_failed_insert_node
{
..
}
=
JSON
.
object
[
"user_id"
.=
toJSON
necin_user_id
,
"parent_id"
.=
necin_parent_id
]
instance
FromJSON
(
ToFrontendErrorData
'E
C
_400__node_creation_failed_insert_node
)
where
parseJSON
=
withObject
"FE_node_creation_failed_insert_node"
$
\
o
->
do
necin_user_id
<-
o
.:
"user_id"
necin_parent_id
<-
o
.:
"parent_id"
pure
FE_node_creation_failed_insert_node
{
..
}
instance
ToJSON
(
ToFrontendErrorData
'E
C
_500__node_generic_exception
)
where
toJSON
FE_node_generic_exception
{
..
}
=
JSON
.
object
[
"error"
.=
nege_error
]
instance
FromJSON
(
ToFrontendErrorData
'E
C
_500__node_generic_exception
)
where
parseJSON
=
withObject
"FE_node_generic_exception"
$
\
o
->
do
nege_error
<-
o
.:
"error"
pure
FE_node_generic_exception
{
..
}
instance
ToJSON
(
ToFrontendErrorData
'E
C
_400__node_needs_configuration
)
where
toJSON
_
=
JSON
.
Null
instance
FromJSON
(
ToFrontendErrorData
'E
C
_400__node_needs_configuration
)
where
parseJSON
_
=
pure
FE_node_needs_configuration
--
--
-- validation errors
-- validation errors
...
@@ -337,75 +470,75 @@ instance FromJSON (ToFrontendErrorData 'EC_500__internal_server_error) where
...
@@ -337,75 +470,75 @@ instance FromJSON (ToFrontendErrorData 'EC_500__internal_server_error) where
-- tree errors
-- tree errors
--
--
instance
ToJSON
(
ToFrontendErrorData
'E
C
_404__tree_
error_
root_not_found
)
where
instance
ToJSON
(
ToFrontendErrorData
'E
C
_404__tree_root_not_found
)
where
toJSON
_
=
JSON
.
Null
toJSON
_
=
JSON
.
Null
instance
FromJSON
(
ToFrontendErrorData
'E
C
_404__tree_
error_
root_not_found
)
where
instance
FromJSON
(
ToFrontendErrorData
'E
C
_404__tree_root_not_found
)
where
parseJSON
_
=
pure
FE_tree_
error_
root_not_found
parseJSON
_
=
pure
FE_tree_root_not_found
instance
ToJSON
(
ToFrontendErrorData
'E
C
_404__tree_e
rror_e
mpty_root
)
where
instance
ToJSON
(
ToFrontendErrorData
'E
C
_404__tree_empty_root
)
where
toJSON
_
=
JSON
.
Null
toJSON
_
=
JSON
.
Null
instance
FromJSON
(
ToFrontendErrorData
'E
C
_404__tree_e
rror_e
mpty_root
)
where
instance
FromJSON
(
ToFrontendErrorData
'E
C
_404__tree_empty_root
)
where
parseJSON
_
=
pure
FE_tree_e
rror_e
mpty_root
parseJSON
_
=
pure
FE_tree_empty_root
instance
ToJSON
(
ToFrontendErrorData
'E
C
_500__tree_
error_
too_many_roots
)
where
instance
ToJSON
(
ToFrontendErrorData
'E
C
_500__tree_too_many_roots
)
where
toJSON
(
FE_tree_
error_
too_many_roots
roots
)
=
toJSON
(
FE_tree_too_many_roots
roots
)
=
object
[
"node_ids"
.=
NE
.
toList
roots
]
object
[
"node_ids"
.=
NE
.
toList
roots
]
instance
FromJSON
(
ToFrontendErrorData
'E
C
_500__tree_
error_
too_many_roots
)
where
instance
FromJSON
(
ToFrontendErrorData
'E
C
_500__tree_too_many_roots
)
where
parseJSON
=
withObject
"FE_tree_
error_
too_many_roots"
$
\
o
->
do
parseJSON
=
withObject
"FE_tree_too_many_roots"
$
\
o
->
do
tmr_roots
<-
o
.:
"node_ids"
tmr_roots
<-
o
.:
"node_ids"
pure
FE_tree_
error_
too_many_roots
{
..
}
pure
FE_tree_too_many_roots
{
..
}
--
--
-- job errors
-- job errors
--
--
instance
ToJSON
(
ToFrontendErrorData
'E
C
_500__job_
error_
invalid_id_type
)
where
instance
ToJSON
(
ToFrontendErrorData
'E
C
_500__job_invalid_id_type
)
where
toJSON
(
FE_job_
error_
invalid_id_type
idTy
)
=
toJSON
(
FE_job_invalid_id_type
idTy
)
=
object
[
"type"
.=
toJSON
idTy
]
object
[
"type"
.=
toJSON
idTy
]
instance
FromJSON
(
ToFrontendErrorData
'E
C
_500__job_
error_
invalid_id_type
)
where
instance
FromJSON
(
ToFrontendErrorData
'E
C
_500__job_invalid_id_type
)
where
parseJSON
=
withObject
"FE_job_
error_
invalid_id_type"
$
\
o
->
do
parseJSON
=
withObject
"FE_job_invalid_id_type"
$
\
o
->
do
jeiit_type
<-
o
.:
"type"
jeiit_type
<-
o
.:
"type"
pure
FE_job_
error_
invalid_id_type
{
..
}
pure
FE_job_invalid_id_type
{
..
}
instance
ToJSON
(
ToFrontendErrorData
'E
C
_500__job_e
rror_e
xpired
)
where
instance
ToJSON
(
ToFrontendErrorData
'E
C
_500__job_expired
)
where
toJSON
(
FE_job_e
rror_e
xpired
jobId
)
=
toJSON
(
FE_job_expired
jobId
)
=
object
[
"job_id"
.=
toJSON
jobId
]
object
[
"job_id"
.=
toJSON
jobId
]
instance
FromJSON
(
ToFrontendErrorData
'E
C
_500__job_e
rror_e
xpired
)
where
instance
FromJSON
(
ToFrontendErrorData
'E
C
_500__job_expired
)
where
parseJSON
=
withObject
"FE_job_e
rror_e
xpired"
$
\
o
->
do
parseJSON
=
withObject
"FE_job_expired"
$
\
o
->
do
jee_job_id
<-
o
.:
"job_id"
jee_job_id
<-
o
.:
"job_id"
pure
FE_job_e
rror_e
xpired
{
..
}
pure
FE_job_expired
{
..
}
instance
ToJSON
(
ToFrontendErrorData
'E
C
_500__job_
error_
invalid_mac
)
where
instance
ToJSON
(
ToFrontendErrorData
'E
C
_500__job_invalid_mac
)
where
toJSON
(
FE_job_
error_
invalid_mac
mac
)
=
toJSON
(
FE_job_invalid_mac
mac
)
=
object
[
"mac"
.=
toJSON
mac
]
object
[
"mac"
.=
toJSON
mac
]
instance
FromJSON
(
ToFrontendErrorData
'E
C
_500__job_
error_
invalid_mac
)
where
instance
FromJSON
(
ToFrontendErrorData
'E
C
_500__job_invalid_mac
)
where
parseJSON
=
withObject
"FE_job_
error_
invalid_mac"
$
\
o
->
do
parseJSON
=
withObject
"FE_job_invalid_mac"
$
\
o
->
do
jeim_mac
<-
o
.:
"mac"
jeim_mac
<-
o
.:
"mac"
pure
FE_job_
error_
invalid_mac
{
..
}
pure
FE_job_invalid_mac
{
..
}
instance
ToJSON
(
ToFrontendErrorData
'E
C
_500__job_
error_
unknown_job
)
where
instance
ToJSON
(
ToFrontendErrorData
'E
C
_500__job_unknown_job
)
where
toJSON
(
FE_job_
error_
unknown_job
jobId
)
=
toJSON
(
FE_job_unknown_job
jobId
)
=
object
[
"job_id"
.=
toJSON
jobId
]
object
[
"job_id"
.=
toJSON
jobId
]
instance
FromJSON
(
ToFrontendErrorData
'E
C
_500__job_
error_
unknown_job
)
where
instance
FromJSON
(
ToFrontendErrorData
'E
C
_500__job_unknown_job
)
where
parseJSON
=
withObject
"FE_job_
error_
unknown_job"
$
\
o
->
do
parseJSON
=
withObject
"FE_job_unknown_job"
$
\
o
->
do
jeuj_job_id
<-
o
.:
"job_id"
jeuj_job_id
<-
o
.:
"job_id"
pure
FE_job_
error_
unknown_job
{
..
}
pure
FE_job_unknown_job
{
..
}
instance
ToJSON
(
ToFrontendErrorData
'E
C
_500__job_
error_
generic_exception
)
where
instance
ToJSON
(
ToFrontendErrorData
'E
C
_500__job_generic_exception
)
where
toJSON
(
FE_job_
error_
generic_exception
err
)
=
toJSON
(
FE_job_generic_exception
err
)
=
object
[
"error"
.=
toJSON
err
]
object
[
"error"
.=
toJSON
err
]
instance
FromJSON
(
ToFrontendErrorData
'E
C
_500__job_
error_
generic_exception
)
where
instance
FromJSON
(
ToFrontendErrorData
'E
C
_500__job_generic_exception
)
where
parseJSON
=
withObject
"FE_job_
error_
generic_exception"
$
\
o
->
do
parseJSON
=
withObject
"FE_job_generic_exception"
$
\
o
->
do
jege_error
<-
o
.:
"error"
jege_error
<-
o
.:
"error"
pure
FE_job_
error_
generic_exception
{
..
}
pure
FE_job_generic_exception
{
..
}
----------------------------------------------------------------------------
----------------------------------------------------------------------------
-- Arbitrary instances and test data generation
-- Arbitrary instances and test data generation
...
@@ -420,17 +553,48 @@ genFrontendErr be = do
...
@@ -420,17 +553,48 @@ genFrontendErr be = do
case
be
of
case
be
of
-- node errors
-- node errors
EC_404__node_
error_
list_not_found
EC_404__node_list_not_found
->
arbitrary
>>=
\
lid
->
pure
$
mkFrontendErr'
txt
$
FE_node_
error_
list_not_found
lid
->
arbitrary
>>=
\
lid
->
pure
$
mkFrontendErr'
txt
$
FE_node_list_not_found
lid
EC_404__node_
error_
root_not_found
EC_404__node_root_not_found
->
pure
$
mkFrontendErr'
txt
FE_node_
error_
root_not_found
->
pure
$
mkFrontendErr'
txt
FE_node_root_not_found
EC_404__node_
error_
corpus_not_found
EC_404__node_corpus_not_found
->
pure
$
mkFrontendErr'
txt
FE_node_
error_
corpus_not_found
->
pure
$
mkFrontendErr'
txt
FE_node_corpus_not_found
EC_500__node_
error_
not_implemented_yet
EC_500__node_not_implemented_yet
->
pure
$
mkFrontendErr'
txt
FE_node_
error_
not_implemented_yet
->
pure
$
mkFrontendErr'
txt
FE_node_not_implemented_yet
EC_404__node_
error
_not_found
EC_404__node_
lookup_failed
_not_found
->
do
nodeId
<-
arbitrary
->
do
nodeId
<-
arbitrary
pure
$
mkFrontendErr'
txt
(
FE_node_error_not_found
nodeId
)
pure
$
mkFrontendErr'
txt
(
FE_node_lookup_failed_not_found
nodeId
)
EC_404__node_lookup_failed_user_not_found
->
do
userId
<-
arbitrary
pure
$
mkFrontendErr'
txt
(
FE_node_lookup_failed_user_not_found
userId
)
EC_404__node_lookup_failed_username_not_found
->
do
username
<-
arbitrary
pure
$
mkFrontendErr'
txt
(
FE_node_lookup_failed_username_not_found
username
)
EC_400__node_lookup_failed_user_too_many_roots
->
do
userId
<-
arbitrary
roots
<-
arbitrary
pure
$
mkFrontendErr'
txt
(
FE_node_lookup_failed_user_too_many_roots
userId
roots
)
EC_404__node_context_not_found
->
do
contextId
<-
arbitrary
pure
$
mkFrontendErr'
txt
(
FE_node_context_not_found
contextId
)
EC_400__node_creation_failed_no_parent
->
do
userId
<-
arbitrary
pure
$
mkFrontendErr'
txt
(
FE_node_creation_failed_no_parent
userId
)
EC_400__node_creation_failed_parent_exists
->
do
userId
<-
arbitrary
parentId
<-
arbitrary
pure
$
mkFrontendErr'
txt
(
FE_node_creation_failed_parent_exists
userId
parentId
)
EC_400__node_creation_failed_insert_node
->
do
userId
<-
arbitrary
parentId
<-
arbitrary
pure
$
mkFrontendErr'
txt
$
FE_node_creation_failed_insert_node
parentId
userId
EC_400__node_creation_failed_user_negative_id
->
pure
$
mkFrontendErr'
txt
(
FE_node_creation_failed_user_negative_id
(
UnsafeMkUserId
(
-
42
)))
EC_500__node_generic_exception
->
do
err
<-
arbitrary
pure
$
mkFrontendErr'
txt
$
FE_node_generic_exception
err
EC_400__node_needs_configuration
->
pure
$
mkFrontendErr'
txt
$
FE_node_needs_configuration
-- validation error
-- validation error
EC_400__validation_error
EC_400__validation_error
...
@@ -450,30 +614,30 @@ genFrontendErr be = do
...
@@ -450,30 +614,30 @@ genFrontendErr be = do
pure
$
mkFrontendErr'
txt
$
FE_internal_server_error
err
pure
$
mkFrontendErr'
txt
$
FE_internal_server_error
err
-- tree errors
-- tree errors
EC_404__tree_
error_
root_not_found
EC_404__tree_root_not_found
->
pure
$
mkFrontendErr'
txt
$
FE_tree_
error_
root_not_found
->
pure
$
mkFrontendErr'
txt
$
FE_tree_root_not_found
EC_404__tree_e
rror_e
mpty_root
EC_404__tree_empty_root
->
pure
$
mkFrontendErr'
txt
$
FE_tree_e
rror_e
mpty_root
->
pure
$
mkFrontendErr'
txt
$
FE_tree_empty_root
EC_500__tree_
error_
too_many_roots
EC_500__tree_too_many_roots
->
do
nodes
<-
arbitrary
->
do
nodes
<-
arbitrary
pure
$
mkFrontendErr'
txt
$
FE_tree_
error_
too_many_roots
nodes
pure
$
mkFrontendErr'
txt
$
FE_tree_too_many_roots
nodes
-- job errors
-- job errors
EC_500__job_
error_
invalid_id_type
EC_500__job_invalid_id_type
->
do
idTy
<-
arbitrary
->
do
idTy
<-
arbitrary
pure
$
mkFrontendErr'
txt
$
FE_job_
error_
invalid_id_type
idTy
pure
$
mkFrontendErr'
txt
$
FE_job_invalid_id_type
idTy
EC_500__job_e
rror_e
xpired
EC_500__job_expired
->
do
jobId
<-
getPositive
<$>
arbitrary
->
do
jobId
<-
getPositive
<$>
arbitrary
pure
$
mkFrontendErr'
txt
$
FE_job_e
rror_e
xpired
jobId
pure
$
mkFrontendErr'
txt
$
FE_job_expired
jobId
EC_500__job_
error_
invalid_mac
EC_500__job_invalid_mac
->
do
macId
<-
arbitrary
->
do
macId
<-
arbitrary
pure
$
mkFrontendErr'
txt
$
FE_job_e
rror_e
xpired
macId
pure
$
mkFrontendErr'
txt
$
FE_job_expired
macId
EC_500__job_
error_
unknown_job
EC_500__job_unknown_job
->
do
jobId
<-
getPositive
<$>
arbitrary
->
do
jobId
<-
getPositive
<$>
arbitrary
pure
$
mkFrontendErr'
txt
$
FE_job_
error_
unknown_job
jobId
pure
$
mkFrontendErr'
txt
$
FE_job_unknown_job
jobId
EC_500__job_
error_
generic_exception
EC_500__job_generic_exception
->
do
err
<-
arbitrary
->
do
err
<-
arbitrary
pure
$
mkFrontendErr'
txt
$
FE_job_
error_
generic_exception
err
pure
$
mkFrontendErr'
txt
$
FE_job_generic_exception
err
instance
ToJSON
BackendErrorCode
where
instance
ToJSON
BackendErrorCode
where
toJSON
=
JSON
.
String
.
T
.
pack
.
drop
3
.
show
toJSON
=
JSON
.
String
.
T
.
pack
.
drop
3
.
show
...
@@ -496,20 +660,50 @@ instance FromJSON FrontendError where
...
@@ -496,20 +660,50 @@ instance FromJSON FrontendError where
(
fe_diagnostic
::
T
.
Text
)
<-
o
.:
"diagnostic"
(
fe_diagnostic
::
T
.
Text
)
<-
o
.:
"diagnostic"
(
fe_type
::
BackendErrorCode
)
<-
o
.:
"type"
(
fe_type
::
BackendErrorCode
)
<-
o
.:
"type"
case
fe_type
of
case
fe_type
of
EC_404__node_error_list_not_found
->
do
EC_404__node_list_not_found
->
do
(
fe_data
::
ToFrontendErrorData
'E
C
_404__node_error_list_not_found
)
<-
o
.:
"data"
(
fe_data
::
ToFrontendErrorData
'E
C
_404__node_list_not_found
)
<-
o
.:
"data"
pure
FrontendError
{
..
}
EC_404__node_root_not_found
->
do
(
fe_data
::
ToFrontendErrorData
'E
C
_404__node_root_not_found
)
<-
o
.:
"data"
pure
FrontendError
{
..
}
EC_404__node_corpus_not_found
->
do
(
fe_data
::
ToFrontendErrorData
'E
C
_404__node_corpus_not_found
)
<-
o
.:
"data"
pure
FrontendError
{
..
}
EC_404__node_lookup_failed_not_found
->
do
(
fe_data
::
ToFrontendErrorData
'E
C
_404__node_lookup_failed_not_found
)
<-
o
.:
"data"
pure
FrontendError
{
..
}
EC_404__node_lookup_failed_user_not_found
->
do
(
fe_data
::
ToFrontendErrorData
'E
C
_404__node_lookup_failed_user_not_found
)
<-
o
.:
"data"
pure
FrontendError
{
..
}
EC_404__node_lookup_failed_username_not_found
->
do
(
fe_data
::
ToFrontendErrorData
'E
C
_404__node_lookup_failed_username_not_found
)
<-
o
.:
"data"
pure
FrontendError
{
..
}
EC_400__node_lookup_failed_user_too_many_roots
->
do
(
fe_data
::
ToFrontendErrorData
'E
C
_400__node_lookup_failed_user_too_many_roots
)
<-
o
.:
"data"
pure
FrontendError
{
..
}
EC_500__node_not_implemented_yet
->
do
(
fe_data
::
ToFrontendErrorData
'E
C
_500__node_not_implemented_yet
)
<-
o
.:
"data"
pure
FrontendError
{
..
}
EC_404__node_context_not_found
->
do
(
fe_data
::
ToFrontendErrorData
'E
C
_404__node_context_not_found
)
<-
o
.:
"data"
pure
FrontendError
{
..
}
EC_400__node_creation_failed_no_parent
->
do
(
fe_data
::
ToFrontendErrorData
'E
C
_400__node_creation_failed_no_parent
)
<-
o
.:
"data"
pure
FrontendError
{
..
}
EC_400__node_creation_failed_parent_exists
->
do
(
fe_data
::
ToFrontendErrorData
'E
C
_400__node_creation_failed_parent_exists
)
<-
o
.:
"data"
pure
FrontendError
{
..
}
pure
FrontendError
{
..
}
EC_40
4__node_error_root_not_found
->
do
EC_40
0__node_creation_failed_insert_node
->
do
(
fe_data
::
ToFrontendErrorData
'E
C
_40
4__node_error_root_not_found
)
<-
o
.:
"data"
(
fe_data
::
ToFrontendErrorData
'E
C
_40
0__node_creation_failed_insert_node
)
<-
o
.:
"data"
pure
FrontendError
{
..
}
pure
FrontendError
{
..
}
EC_40
4__node_error_corpus_not_found
->
do
EC_40
0__node_creation_failed_user_negative_id
->
do
(
fe_data
::
ToFrontendErrorData
'E
C
_40
4__node_error_corpus_not_foun
d
)
<-
o
.:
"data"
(
fe_data
::
ToFrontendErrorData
'E
C
_40
0__node_creation_failed_user_negative_i
d
)
<-
o
.:
"data"
pure
FrontendError
{
..
}
pure
FrontendError
{
..
}
EC_
404__node_error_not_found
->
do
EC_
500__node_generic_exception
->
do
(
fe_data
::
ToFrontendErrorData
'E
C
_
404__node_error_not_found
)
<-
o
.:
"data"
(
fe_data
::
ToFrontendErrorData
'E
C
_
500__node_generic_exception
)
<-
o
.:
"data"
pure
FrontendError
{
..
}
pure
FrontendError
{
..
}
EC_
500__node_error_not_implemented_yet
->
do
EC_
400__node_needs_configuration
->
do
(
fe_data
::
ToFrontendErrorData
'E
C
_
500__node_error_not_implemented_yet
)
<-
o
.:
"data"
(
fe_data
::
ToFrontendErrorData
'E
C
_
400__node_needs_configuration
)
<-
o
.:
"data"
pure
FrontendError
{
..
}
pure
FrontendError
{
..
}
-- validation error
-- validation error
...
@@ -528,29 +722,29 @@ instance FromJSON FrontendError where
...
@@ -528,29 +722,29 @@ instance FromJSON FrontendError where
pure
FrontendError
{
..
}
pure
FrontendError
{
..
}
-- tree errors
-- tree errors
EC_404__tree_
error_
root_not_found
->
do
EC_404__tree_root_not_found
->
do
(
fe_data
::
ToFrontendErrorData
'E
C
_404__tree_
error_
root_not_found
)
<-
o
.:
"data"
(
fe_data
::
ToFrontendErrorData
'E
C
_404__tree_root_not_found
)
<-
o
.:
"data"
pure
FrontendError
{
..
}
pure
FrontendError
{
..
}
EC_404__tree_e
rror_e
mpty_root
->
do
EC_404__tree_empty_root
->
do
(
fe_data
::
ToFrontendErrorData
'E
C
_404__tree_e
rror_e
mpty_root
)
<-
o
.:
"data"
(
fe_data
::
ToFrontendErrorData
'E
C
_404__tree_empty_root
)
<-
o
.:
"data"
pure
FrontendError
{
..
}
pure
FrontendError
{
..
}
EC_500__tree_
error_
too_many_roots
->
do
EC_500__tree_too_many_roots
->
do
(
fe_data
::
ToFrontendErrorData
'E
C
_500__tree_
error_
too_many_roots
)
<-
o
.:
"data"
(
fe_data
::
ToFrontendErrorData
'E
C
_500__tree_too_many_roots
)
<-
o
.:
"data"
pure
FrontendError
{
..
}
pure
FrontendError
{
..
}
-- job errors
-- job errors
EC_500__job_
error_
invalid_id_type
->
do
EC_500__job_invalid_id_type
->
do
(
fe_data
::
ToFrontendErrorData
'E
C
_500__job_
error_
invalid_id_type
)
<-
o
.:
"data"
(
fe_data
::
ToFrontendErrorData
'E
C
_500__job_invalid_id_type
)
<-
o
.:
"data"
pure
FrontendError
{
..
}
pure
FrontendError
{
..
}
EC_500__job_e
rror_e
xpired
->
do
EC_500__job_expired
->
do
(
fe_data
::
ToFrontendErrorData
'E
C
_500__job_e
rror_e
xpired
)
<-
o
.:
"data"
(
fe_data
::
ToFrontendErrorData
'E
C
_500__job_expired
)
<-
o
.:
"data"
pure
FrontendError
{
..
}
pure
FrontendError
{
..
}
EC_500__job_
error_
invalid_mac
->
do
EC_500__job_invalid_mac
->
do
(
fe_data
::
ToFrontendErrorData
'E
C
_500__job_
error_
invalid_mac
)
<-
o
.:
"data"
(
fe_data
::
ToFrontendErrorData
'E
C
_500__job_invalid_mac
)
<-
o
.:
"data"
pure
FrontendError
{
..
}
pure
FrontendError
{
..
}
EC_500__job_
error_
unknown_job
->
do
EC_500__job_unknown_job
->
do
(
fe_data
::
ToFrontendErrorData
'E
C
_500__job_
error_
unknown_job
)
<-
o
.:
"data"
(
fe_data
::
ToFrontendErrorData
'E
C
_500__job_unknown_job
)
<-
o
.:
"data"
pure
FrontendError
{
..
}
pure
FrontendError
{
..
}
EC_500__job_
error_
generic_exception
->
do
EC_500__job_generic_exception
->
do
(
fe_data
::
ToFrontendErrorData
'E
C
_500__job_
error_
generic_exception
)
<-
o
.:
"data"
(
fe_data
::
ToFrontendErrorData
'E
C
_500__job_generic_exception
)
<-
o
.:
"data"
pure
FrontendError
{
..
}
pure
FrontendError
{
..
}
src/Gargantext/API/Errors/Types/Backend.hs
View file @
3763d0dc
...
@@ -16,27 +16,37 @@ import Prelude
...
@@ -16,27 +16,37 @@ import Prelude
data
BackendErrorCode
data
BackendErrorCode
=
=
-- node errors
-- node errors
EC_404__node_error_list_not_found
EC_404__node_list_not_found
|
EC_404__node_error_root_not_found
|
EC_404__node_root_not_found
|
EC_404__node_error_not_found
|
EC_404__node_lookup_failed_not_found
|
EC_404__node_error_corpus_not_found
|
EC_400__node_lookup_failed_user_too_many_roots
|
EC_500__node_error_not_implemented_yet
|
EC_404__node_lookup_failed_user_not_found
|
EC_404__node_lookup_failed_username_not_found
|
EC_404__node_corpus_not_found
|
EC_500__node_not_implemented_yet
|
EC_404__node_context_not_found
|
EC_400__node_creation_failed_no_parent
|
EC_400__node_creation_failed_parent_exists
|
EC_400__node_creation_failed_insert_node
|
EC_400__node_creation_failed_user_negative_id
|
EC_500__node_generic_exception
|
EC_400__node_needs_configuration
-- validation errors
-- validation errors
|
EC_400__validation_error
|
EC_400__validation_error
-- authentication errors
-- authentication errors
|
EC_403__login_failed_error
|
EC_403__login_failed_error
-- tree errors
-- tree errors
|
EC_404__tree_
error_
root_not_found
|
EC_404__tree_root_not_found
|
EC_404__tree_e
rror_e
mpty_root
|
EC_404__tree_empty_root
|
EC_500__tree_
error_
too_many_roots
|
EC_500__tree_too_many_roots
-- internal server errors
-- internal server errors
|
EC_500__internal_server_error
|
EC_500__internal_server_error
-- job errors
-- job errors
|
EC_500__job_
error_
invalid_id_type
|
EC_500__job_invalid_id_type
|
EC_500__job_e
rror_e
xpired
|
EC_500__job_expired
|
EC_500__job_
error_
invalid_mac
|
EC_500__job_invalid_mac
|
EC_500__job_
error_
unknown_job
|
EC_500__job_unknown_job
|
EC_500__job_
error_
generic_exception
|
EC_500__job_generic_exception
deriving
(
Show
,
Read
,
Eq
,
Enum
,
Bounded
)
deriving
(
Show
,
Read
,
Eq
,
Enum
,
Bounded
)
$
(
genSingletons
[
''
B
ackendErrorCode
])
$
(
genSingletons
[
''
B
ackendErrorCode
])
...
...
src/Gargantext/API/Node/Share.hs
View file @
3763d0dc
...
@@ -67,10 +67,10 @@ api userInviting nId (ShareTeamParams user') = do
...
@@ -67,10 +67,10 @@ api userInviting nId (ShareTeamParams user') = do
Just
(
u
,
_
)
->
do
Just
(
u
,
_
)
->
do
isRegistered
<-
getUserId'
(
UserName
u
)
isRegistered
<-
getUserId'
(
UserName
u
)
case
isRegistered
of
case
isRegistered
of
Jus
t
_
->
do
Righ
t
_
->
do
-- printDebug "[G.A.N.Share.api]" ("Team shared with " <> u)
-- printDebug "[G.A.N.Share.api]" ("Team shared with " <> u)
pure
u
pure
u
Nothing
->
do
Left
_err
->
do
username'
<-
getUsername
userInviting
username'
<-
getUsername
userInviting
_
<-
case
List
.
elem
username'
arbitraryUsername
of
_
<-
case
List
.
elem
username'
arbitraryUsername
of
True
->
do
True
->
do
...
...
src/Gargantext/Core/Types/Individu.hs
View file @
3763d0dc
...
@@ -28,7 +28,7 @@ import Gargantext.Prelude.Crypto.Auth qualified as Auth
...
@@ -28,7 +28,7 @@ import Gargantext.Prelude.Crypto.Auth qualified as Auth
import
Prelude
qualified
import
Prelude
qualified
-- FIXME UserName used twice
-- FIXME UserName used twice
data
User
=
UserDBId
UserId
|
UserName
Text
|
RootId
NodeId
|
UserPublic
data
User
=
UserDBId
UserId
|
UserName
Text
|
RootId
NodeId
deriving
(
Eq
)
deriving
(
Eq
)
renderUser
::
User
->
T
.
Text
renderUser
::
User
->
T
.
Text
...
@@ -36,7 +36,6 @@ renderUser = \case
...
@@ -36,7 +36,6 @@ renderUser = \case
UserDBId
urId
->
T
.
pack
(
show
urId
)
UserDBId
urId
->
T
.
pack
(
show
urId
)
UserName
txt
->
txt
UserName
txt
->
txt
RootId
nId
->
T
.
pack
(
show
nId
)
RootId
nId
->
T
.
pack
(
show
nId
)
UserPublic
->
T
.
pack
"public"
type
Username
=
Text
type
Username
=
Text
...
...
src/Gargantext/Database/Action/Node.hs
View file @
3763d0dc
...
@@ -42,14 +42,14 @@ mkNodeWithParent :: (HasNodeError err, HasDBid NodeType)
...
@@ -42,14 +42,14 @@ mkNodeWithParent :: (HasNodeError err, HasDBid NodeType)
->
UserId
->
UserId
->
Name
->
Name
->
DBCmd
err
[
NodeId
]
->
DBCmd
err
[
NodeId
]
mkNodeWithParent
NodeUser
(
Just
_
)
_
_
=
nodeError
UserNoParent
mkNodeWithParent
NodeUser
(
Just
pId
)
uid
_
=
nodeError
$
NodeCreationFailed
$
UserParentAlreadyExists
uid
pId
------------------------------------------------------------------------
------------------------------------------------------------------------
-- | MkNode, insert and eventually configure Hyperdata
-- | MkNode, insert and eventually configure Hyperdata
mkNodeWithParent
NodeUser
Nothing
uId
name
=
mkNodeWithParent
NodeUser
Nothing
uId
name
=
insertNodesWithParentR
Nothing
[
node
NodeUser
name
defaultHyperdataUser
Nothing
uId
]
insertNodesWithParentR
Nothing
[
node
NodeUser
name
defaultHyperdataUser
Nothing
uId
]
mkNodeWithParent
_
Nothing
_
_
=
nodeError
HasParent
mkNodeWithParent
_
Nothing
uId
_
=
nodeError
$
NodeCreationFailed
$
UserParentDoesNotExist
uId
------------------------------------------------------------------------
------------------------------------------------------------------------
mkNodeWithParent
Notes
i
u
n
=
mkNodeWithParent
Notes
i
u
n
=
mkNodeWithParent_ConfigureHyperdata
Notes
i
u
n
mkNodeWithParent_ConfigureHyperdata
Notes
i
u
n
...
@@ -65,7 +65,7 @@ mkNodeWithParent NodeFrameNotebook i u n =
...
@@ -65,7 +65,7 @@ mkNodeWithParent NodeFrameNotebook i u n =
mkNodeWithParent
nt
(
Just
pId
)
uId
name
=
insertNode
nt
(
Just
name
)
Nothing
pId
uId
mkNodeWithParent
nt
(
Just
pId
)
uId
name
=
(
:
[]
)
<$>
insertNode
nt
(
Just
name
)
Nothing
pId
uId
-- mkNodeWithParent _ _ _ _ = errorWith "[G.D.A.Node.mkNodeWithParent] nees parent"
-- mkNodeWithParent _ _ _ _ = errorWith "[G.D.A.Node.mkNodeWithParent] nees parent"
...
@@ -85,7 +85,7 @@ mkNodeWithParent_ConfigureHyperdata Calc (Just i) uId name =
...
@@ -85,7 +85,7 @@ mkNodeWithParent_ConfigureHyperdata Calc (Just i) uId name =
mkNodeWithParent_ConfigureHyperdata
NodeFrameVisio
(
Just
i
)
uId
name
=
mkNodeWithParent_ConfigureHyperdata
NodeFrameVisio
(
Just
i
)
uId
name
=
mkNodeWithParent_ConfigureHyperdata'
NodeFrameVisio
(
Just
i
)
uId
name
mkNodeWithParent_ConfigureHyperdata'
NodeFrameVisio
(
Just
i
)
uId
name
mkNodeWithParent_ConfigureHyperdata
NodeFrameNotebook
(
Just
i
)
uId
name
=
mkNodeWithParent_ConfigureHyperdata
NodeFrameNotebook
(
Just
i
)
uId
name
=
(
:
[]
)
<$>
insertNode
NodeFrameNotebook
(
Just
"Notebook"
)
insertNode
NodeFrameNotebook
(
Just
"Notebook"
)
(
Just
$
DefaultFrameCode
$
HyperdataFrame
{
_hf_base
=
"Codebook"
(
Just
$
DefaultFrameCode
$
HyperdataFrame
{
_hf_base
=
"Codebook"
,
_hf_frame_id
=
name
})
i
uId
,
_hf_frame_id
=
name
})
i
uId
...
@@ -101,26 +101,21 @@ mkNodeWithParent_ConfigureHyperdata' :: (HasNodeError err, HasDBid NodeType)
...
@@ -101,26 +101,21 @@ mkNodeWithParent_ConfigureHyperdata' :: (HasNodeError err, HasDBid NodeType)
->
Name
->
Name
->
DBCmd
err
[
NodeId
]
->
DBCmd
err
[
NodeId
]
mkNodeWithParent_ConfigureHyperdata'
nt
(
Just
i
)
uId
name
=
do
mkNodeWithParent_ConfigureHyperdata'
nt
(
Just
i
)
uId
name
=
do
maybeN
odeId
<-
case
nt
of
n
odeId
<-
case
nt
of
Notes
->
insertNode
Notes
(
Just
name
)
Nothing
i
uId
Notes
->
insertNode
Notes
(
Just
name
)
Nothing
i
uId
Calc
->
insertNode
Calc
(
Just
name
)
Nothing
i
uId
Calc
->
insertNode
Calc
(
Just
name
)
Nothing
i
uId
NodeFrameVisio
->
insertNode
NodeFrameVisio
(
Just
name
)
Nothing
i
uId
NodeFrameVisio
->
insertNode
NodeFrameVisio
(
Just
name
)
Nothing
i
uId
_
->
nodeError
NeedsConfiguration
_
->
nodeError
NeedsConfiguration
case
maybeNodeId
of
cfg
<-
view
hasConfig
[]
->
nodeError
(
DoesNotExist
i
)
u
<-
case
nt
of
[
n
]
->
do
Notes
->
pure
$
_gc_frame_write_url
cfg
cfg
<-
view
hasConfig
Calc
->
pure
$
_gc_frame_calc_url
cfg
u
<-
case
nt
of
NodeFrameVisio
->
pure
$
_gc_frame_visio_url
cfg
Notes
->
pure
$
_gc_frame_write_url
cfg
_
->
nodeError
NeedsConfiguration
Calc
->
pure
$
_gc_frame_calc_url
cfg
let
NodeFrameVisio
->
pure
$
_gc_frame_visio_url
cfg
s
=
_gc_secretkey
cfg
_
->
nodeError
NeedsConfiguration
hd
=
HyperdataFrame
u
(
hash
$
s
<>
(
show
nodeId
))
let
_
<-
updateHyperdata
nodeId
hd
s
=
_gc_secretkey
cfg
pure
[
nodeId
]
hd
=
HyperdataFrame
u
(
hash
$
s
<>
(
show
n
))
mkNodeWithParent_ConfigureHyperdata'
_
Nothing
uId
_
=
nodeError
$
NodeCreationFailed
$
UserParentDoesNotExist
uId
_
<-
updateHyperdata
n
hd
pure
[
n
]
(
_
:
_
:
_
)
->
nodeError
MkNode
mkNodeWithParent_ConfigureHyperdata'
_
_
_
_
=
nodeError
HasParent
src/Gargantext/Database/Action/User.hs
View file @
3763d0dc
...
@@ -27,7 +27,7 @@ getUserLightWithId :: HasNodeError err => UserId -> DBCmd err UserLight
...
@@ -27,7 +27,7 @@ getUserLightWithId :: HasNodeError err => UserId -> DBCmd err UserLight
getUserLightWithId
i
=
do
getUserLightWithId
i
=
do
candidates
<-
head
<$>
getUsersWithId
(
UserDBId
i
)
candidates
<-
head
<$>
getUsersWithId
(
UserDBId
i
)
case
candidates
of
case
candidates
of
Nothing
->
nodeError
(
No
UserFound
(
UserDBId
i
)
)
Nothing
->
nodeError
(
No
deLookupFailed
$
UserDoesNotExist
i
)
Just
u
->
pure
u
Just
u
->
pure
u
getUserLightDB
::
HasNodeError
err
=>
User
->
DBCmd
err
UserLight
getUserLightDB
::
HasNodeError
err
=>
User
->
DBCmd
err
UserLight
...
@@ -43,22 +43,21 @@ getUserId :: HasNodeError err
...
@@ -43,22 +43,21 @@ getUserId :: HasNodeError err
getUserId
u
=
do
getUserId
u
=
do
maybeUser
<-
getUserId'
u
maybeUser
<-
getUserId'
u
case
maybeUser
of
case
maybeUser
of
Nothing
->
nodeError
(
NoUserFound
u
)
Left
reason
->
nodeError
$
NodeLookupFailed
reason
Just
u'
->
pure
u'
Right
u'
->
pure
u'
getUserId'
::
HasNodeError
err
getUserId'
::
HasNodeError
err
=>
User
=>
User
->
DBCmd
err
(
Maybe
UserId
)
->
DBCmd
err
(
Either
NodeLookupError
UserId
)
getUserId'
(
UserDBId
uid
)
=
pure
(
Jus
t
uid
)
getUserId'
(
UserDBId
uid
)
=
pure
(
Righ
t
uid
)
getUserId'
(
RootId
rid
)
=
do
getUserId'
(
RootId
rid
)
=
do
n
<-
getNode
rid
n
<-
getNode
rid
pure
$
Jus
t
$
_node_user_id
n
pure
$
Righ
t
$
_node_user_id
n
getUserId'
(
UserName
u
)
=
do
getUserId'
(
UserName
u
)
=
do
muser
<-
getUser
u
muser
<-
getUser
u
case
muser
of
case
muser
of
Just
user
->
pure
$
Just
$
userLight_id
user
Just
user
->
pure
$
Right
$
userLight_id
user
Nothing
->
pure
Nothing
Nothing
->
pure
$
Left
$
UserNameDoesNotExist
u
getUserId'
UserPublic
=
pure
Nothing
------------------------------------------------------------------------
------------------------------------------------------------------------
-- | Username = Text
-- | Username = Text
...
@@ -73,11 +72,10 @@ getUsername user@(UserDBId _) = do
...
@@ -73,11 +72,10 @@ getUsername user@(UserDBId _) = do
users
<-
getUsersWithId
user
users
<-
getUsersWithId
user
case
head
users
of
case
head
users
of
Just
u
->
pure
$
userLight_username
u
Just
u
->
pure
$
userLight_username
u
Nothing
->
nodeError
$
NodeError
"G.D.A.U.getUserName: User not found with that id"
Nothing
->
errorWith
"G.D.A.U.getUserName: User not found with that id"
getUsername
(
RootId
rid
)
=
do
getUsername
(
RootId
rid
)
=
do
n
<-
getNode
rid
n
<-
getNode
rid
getUsername
(
UserDBId
$
_node_user_id
n
)
getUsername
(
UserDBId
$
_node_user_id
n
)
getUsername
UserPublic
=
pure
"UserPublic"
--------------------------------------------------------------------------
--------------------------------------------------------------------------
-- getRootId is in Gargantext.Database.Query.Tree.Root
-- getRootId is in Gargantext.Database.Query.Tree.Root
src/Gargantext/Database/Action/User/New.hs
View file @
3763d0dc
...
@@ -40,6 +40,7 @@ import Gargantext.Database.Query.Table.User
...
@@ -40,6 +40,7 @@ import Gargantext.Database.Query.Table.User
import
Gargantext.Prelude
import
Gargantext.Prelude
import
Gargantext.Prelude.Crypto.Pass.User
(
gargPass
)
import
Gargantext.Prelude.Crypto.Pass.User
(
gargPass
)
import
Gargantext.Prelude.Mail.Types
(
MailConfig
)
import
Gargantext.Prelude.Mail.Types
(
MailConfig
)
import
qualified
Data.List.NonEmpty
as
NE
------------------------------------------------------------------------
------------------------------------------------------------------------
-- | Creates a new 'User' from the input 'EmailAddress', which needs to
-- | Creates a new 'User' from the input 'EmailAddress', which needs to
...
@@ -63,10 +64,8 @@ new_user :: HasNodeError err
...
@@ -63,10 +64,8 @@ new_user :: HasNodeError err
=>
NewUser
GargPassword
=>
NewUser
GargPassword
->
DBCmd
err
UserId
->
DBCmd
err
UserId
new_user
rq
=
do
new_user
rq
=
do
ur
<-
new_users
[
rq
]
(
uid
NE
.:|
_
)
<-
new_users
(
rq
NE
.:|
[]
)
case
head
ur
of
pure
uid
Nothing
->
nodeError
MkNode
Just
uid
->
pure
uid
------------------------------------------------------------------------
------------------------------------------------------------------------
-- | A DB-specific action to bulk-create users.
-- | A DB-specific action to bulk-create users.
...
@@ -74,18 +73,18 @@ new_user rq = do
...
@@ -74,18 +73,18 @@ new_user rq = do
-- notification, and thus lives in the 'DbCmd' effect stack. You may want to
-- notification, and thus lives in the 'DbCmd' effect stack. You may want to
-- use 'newUsers' instead for standard Gargantext code.
-- use 'newUsers' instead for standard Gargantext code.
new_users
::
HasNodeError
err
new_users
::
HasNodeError
err
=>
[
NewUser
GargPassword
]
=>
NonEmpty
(
NewUser
GargPassword
)
-- ^ A list of users to create.
-- ^ A list of users to create.
->
DBCmd
err
[
UserId
]
->
DBCmd
err
(
NonEmpty
UserId
)
new_users
us
=
do
new_users
us
=
do
us'
<-
liftBase
$
mapM
toUserHash
us
us'
<-
liftBase
$
mapM
toUserHash
us
void
$
insertUsers
$
map
toUserWrite
us'
void
$
insertUsers
$
NE
.
map
toUserWrite
us'
mapM
(
fmap
fst
.
getOrMkRoot
)
$
map
(
\
u
->
UserName
(
_nu_username
u
))
us
mapM
(
fmap
fst
.
getOrMkRoot
)
$
NE
.
map
(
\
u
->
UserName
(
_nu_username
u
))
us
------------------------------------------------------------------------
------------------------------------------------------------------------
newUsers
::
(
CmdM
env
err
m
,
MonadRandom
m
,
HasNodeError
err
,
HasMail
env
)
newUsers
::
(
CmdM
env
err
m
,
MonadRandom
m
,
HasNodeError
err
,
HasMail
env
)
=>
[
EmailAddress
]
=>
NonEmpty
EmailAddress
->
m
[
UserId
]
->
m
(
NonEmpty
UserId
)
newUsers
us
=
do
newUsers
us
=
do
config
<-
view
$
mailSettings
config
<-
view
$
mailSettings
us'
<-
mapM
(
\
ea
->
mkNewUser
ea
.
GargPassword
<$>
gargPass
)
us
us'
<-
mapM
(
\
ea
->
mkNewUser
ea
.
GargPassword
<$>
gargPass
)
us
...
@@ -110,10 +109,10 @@ guessUserName n = case splitOn "@" n of
...
@@ -110,10 +109,10 @@ guessUserName n = case splitOn "@" n of
------------------------------------------------------------------------
------------------------------------------------------------------------
newUsers'
::
HasNodeError
err
newUsers'
::
HasNodeError
err
=>
MailConfig
->
[
NewUser
GargPassword
]
->
Cmd
err
[
UserId
]
=>
MailConfig
->
NonEmpty
(
NewUser
GargPassword
)
->
Cmd
err
(
NonEmpty
UserId
)
newUsers'
cfg
us
=
do
newUsers'
cfg
us
=
do
us'
<-
liftBase
$
mapM
toUserHash
us
us'
<-
liftBase
$
mapM
toUserHash
us
void
$
insertUsers
$
map
toUserWrite
us'
void
$
insertUsers
$
NE
.
map
toUserWrite
us'
urs
<-
mapM
(
fmap
fst
.
getOrMkRoot
)
$
map
(
\
u
->
UserName
(
_nu_username
u
))
us
urs
<-
mapM
(
fmap
fst
.
getOrMkRoot
)
$
map
(
\
u
->
UserName
(
_nu_username
u
))
us
_
<-
mapM
(
\
u
->
mail
cfg
(
Invitation
u
))
us
_
<-
mapM
(
\
u
->
mail
cfg
(
Invitation
u
))
us
-- printDebug "newUsers'" us
-- printDebug "newUsers'" us
...
...
src/Gargantext/Database/Admin/Types/Node.hs
View file @
3763d0dc
...
@@ -275,6 +275,9 @@ newtype ContextId = UnsafeMkContextId { _ContextId :: Int }
...
@@ -275,6 +275,9 @@ newtype ContextId = UnsafeMkContextId { _ContextId :: Int }
instance
ToParamSchema
ContextId
instance
ToParamSchema
ContextId
instance
Arbitrary
ContextId
where
arbitrary
=
UnsafeMkContextId
.
getPositive
<$>
arbitrary
instance
FromHttpApiData
ContextId
where
instance
FromHttpApiData
ContextId
where
parseUrlPiece
n
=
pure
$
UnsafeMkContextId
$
(
read
.
cs
)
n
parseUrlPiece
n
=
pure
$
UnsafeMkContextId
$
(
read
.
cs
)
n
instance
ToHttpApiData
ContextId
where
instance
ToHttpApiData
ContextId
where
...
...
src/Gargantext/Database/Query/Table/Node.hs
View file @
3763d0dc
...
@@ -266,21 +266,25 @@ getNodeWith nId _ = do
...
@@ -266,21 +266,25 @@ getNodeWith nId _ = do
------------------------------------------------------------------------
------------------------------------------------------------------------
-- | Sugar to insert Node with NodeType in Database
-- | Sugar to insert Node with NodeType in Database
insertDefaultNode
::
HasDBid
NodeType
insertDefaultNode
::
(
HasDBid
NodeType
,
HasNodeError
err
)
=>
NodeType
->
ParentId
->
UserId
->
DBCmd
err
[
NodeId
]
=>
NodeType
->
ParentId
->
UserId
->
DBCmd
err
NodeId
insertDefaultNode
nt
p
u
=
insertNode
nt
Nothing
Nothing
p
u
insertDefaultNode
nt
p
u
=
insertNode
nt
Nothing
Nothing
p
u
insertDefaultNodeIfNotExists
::
HasDBid
NodeType
insertDefaultNodeIfNotExists
::
(
HasDBid
NodeType
,
HasNodeError
err
)
=>
NodeType
->
ParentId
->
UserId
->
DBCmd
err
[
NodeId
]
=>
NodeType
->
ParentId
->
UserId
->
DBCmd
err
[
NodeId
]
insertDefaultNodeIfNotExists
nt
p
u
=
do
insertDefaultNodeIfNotExists
nt
p
u
=
do
children
<-
getChildrenByType
p
nt
children
<-
getChildrenByType
p
nt
case
children
of
case
children
of
[]
->
insertDefaultNode
nt
p
u
[]
->
(
:
[]
)
<$>
insertDefaultNode
nt
p
u
xs
->
pure
xs
xs
->
pure
xs
insertNode
::
HasDBid
NodeType
insertNode
::
(
HasDBid
NodeType
,
HasNodeError
err
)
=>
NodeType
->
Maybe
Name
->
Maybe
DefaultHyperdata
->
ParentId
->
UserId
->
DBCmd
err
[
NodeId
]
=>
NodeType
->
Maybe
Name
->
Maybe
DefaultHyperdata
->
ParentId
->
UserId
->
DBCmd
err
NodeId
insertNode
nt
n
h
p
u
=
insertNodesR
[
nodeW
nt
n
h
p
u
]
insertNode
nt
n
h
p
u
=
do
res
<-
insertNodesR
[
nodeW
nt
n
h
p
u
]
case
res
of
[
x
]
->
pure
x
_
->
nodeError
$
NodeCreationFailed
$
InsertNodeFailed
u
p
nodeW
::
HasDBid
NodeType
nodeW
::
HasDBid
NodeType
=>
NodeType
->
Maybe
Name
->
Maybe
DefaultHyperdata
->
ParentId
->
UserId
->
NodeWrite
=>
NodeType
->
Maybe
Name
->
Maybe
DefaultHyperdata
->
ParentId
->
UserId
->
NodeWrite
...
@@ -378,18 +382,18 @@ data CorpusType = CorpusDocument | CorpusContact
...
@@ -378,18 +382,18 @@ data CorpusType = CorpusDocument | CorpusContact
class
MkCorpus
a
class
MkCorpus
a
where
where
mk
::
HasDBid
NodeType
=>
Maybe
Name
->
Maybe
a
->
ParentId
->
UserId
->
DBCmd
err
[
NodeId
]
mk
::
(
HasDBid
NodeType
,
HasNodeError
err
)
=>
Maybe
Name
->
Maybe
a
->
ParentId
->
UserId
->
DBCmd
err
[
NodeId
]
instance
MkCorpus
HyperdataCorpus
instance
MkCorpus
HyperdataCorpus
where
where
mk
n
Nothing
p
u
=
insertNode
NodeCorpus
n
Nothing
p
u
mk
n
Nothing
p
u
=
(
:
[]
)
<$>
insertNode
NodeCorpus
n
Nothing
p
u
mk
n
(
Just
h
)
p
u
=
insertNode
NodeCorpus
n
(
Just
$
DefaultCorpus
h
)
p
u
mk
n
(
Just
h
)
p
u
=
(
:
[]
)
<$>
insertNode
NodeCorpus
n
(
Just
$
DefaultCorpus
h
)
p
u
instance
MkCorpus
HyperdataAnnuaire
instance
MkCorpus
HyperdataAnnuaire
where
where
mk
n
Nothing
p
u
=
insertNode
NodeCorpus
n
Nothing
p
u
mk
n
Nothing
p
u
=
(
:
[]
)
<$>
insertNode
NodeCorpus
n
Nothing
p
u
mk
n
(
Just
h
)
p
u
=
insertNode
NodeAnnuaire
n
(
Just
$
DefaultAnnuaire
h
)
p
u
mk
n
(
Just
h
)
p
u
=
(
:
[]
)
<$>
insertNode
NodeAnnuaire
n
(
Just
$
DefaultAnnuaire
h
)
p
u
getOrMkList
::
(
HasNodeError
err
,
HasDBid
NodeType
)
getOrMkList
::
(
HasNodeError
err
,
HasDBid
NodeType
)
...
@@ -399,7 +403,7 @@ getOrMkList :: (HasNodeError err, HasDBid NodeType)
...
@@ -399,7 +403,7 @@ getOrMkList :: (HasNodeError err, HasDBid NodeType)
getOrMkList
pId
uId
=
getOrMkList
pId
uId
=
maybe
(
mkList'
pId
uId
)
(
pure
.
view
node_id
)
.
headMay
=<<
getListsWithParentId
pId
maybe
(
mkList'
pId
uId
)
(
pure
.
view
node_id
)
.
headMay
=<<
getListsWithParentId
pId
where
where
mkList'
pId'
uId'
=
maybe
(
nodeError
MkNode
)
pure
.
headMay
=<<
insertDefaultNode
NodeList
pId'
uId'
mkList'
pId'
uId'
=
insertDefaultNode
NodeList
pId'
uId'
-- | TODO remove defaultList
-- | TODO remove defaultList
defaultList
::
(
HasNodeError
err
,
HasDBid
NodeType
)
=>
CorpusId
->
DBCmd
err
ListId
defaultList
::
(
HasNodeError
err
,
HasDBid
NodeType
)
=>
CorpusId
->
DBCmd
err
ListId
...
...
src/Gargantext/Database/Query/Table/Node/Error.hs
View file @
3763d0dc
{-# LANGUAGE LambdaCase #-}
{-|
{-|
Module : Gargantext.Database.Types.Error
Module : Gargantext.Database.Types.Error
Description :
Description :
...
@@ -17,27 +18,49 @@ import Gargantext.Core.Types.Individu
...
@@ -17,27 +18,49 @@ import Gargantext.Core.Types.Individu
import
Prelude
hiding
(
null
,
id
,
map
,
sum
,
show
)
import
Prelude
hiding
(
null
,
id
,
map
,
sum
,
show
)
import
Gargantext.Database.Admin.Types.Node
(
ListId
,
NodeId
(
..
),
ContextId
)
import
Gargantext.Database.Admin.Types.Node
(
ListId
,
NodeId
(
..
),
ContextId
,
UserId
,
ParentId
)
import
Gargantext.Prelude
hiding
(
sum
,
head
)
import
Gargantext.Prelude
hiding
(
sum
,
head
)
import
Prelude
qualified
import
Prelude
qualified
data
NodeCreationError
=
UserParentAlreadyExists
UserId
ParentId
|
UserParentDoesNotExist
UserId
|
UserHasNegativeId
UserId
|
InsertNodeFailed
UserId
ParentId
renderNodeCreationFailed
::
NodeCreationError
->
T
.
Text
renderNodeCreationFailed
=
\
case
UserParentAlreadyExists
uid
pId
->
"user id "
<>
T
.
pack
(
show
uid
)
<>
" has already a parent: "
<>
T
.
pack
(
show
pId
)
UserParentDoesNotExist
uid
->
"user id "
<>
T
.
pack
(
show
uid
)
<>
" has no parent"
UserHasNegativeId
uid
->
"user id "
<>
T
.
pack
(
show
uid
)
<>
" is a negative id."
InsertNodeFailed
uid
pid
->
"couldn't create the list for user id "
<>
T
.
pack
(
show
uid
)
<>
" and parent id "
<>
T
.
pack
(
show
pid
)
data
NodeLookupError
=
NodeDoesNotExist
NodeId
|
UserDoesNotExist
UserId
|
UserNameDoesNotExist
Username
|
UserHasTooManyRoots
UserId
[
NodeId
]
renderNodeLookupFailed
::
NodeLookupError
->
T
.
Text
renderNodeLookupFailed
=
\
case
NodeDoesNotExist
nid
->
"node with id "
<>
T
.
pack
(
show
nid
)
<>
" couldn't be found."
UserDoesNotExist
uid
->
"user with id "
<>
T
.
pack
(
show
uid
)
<>
" couldn't be found."
UserNameDoesNotExist
uname
->
"user with username '"
<>
uname
<>
" couldn't be found."
UserHasTooManyRoots
uid
roots
->
"user with id "
<>
T
.
pack
(
show
uid
)
<>
" has too many roots: ["
<>
T
.
intercalate
","
(
map
(
T
.
pack
.
show
)
roots
)
------------------------------------------------------------------------
------------------------------------------------------------------------
data
NodeError
=
NoListFound
ListId
data
NodeError
=
NoListFound
ListId
|
NoRootFound
|
NoRootFound
|
NoCorpusFound
|
NoCorpusFound
|
NoUserFound
User
|
NoUserFound
User
|
MkNode
|
NodeCreationFailed
NodeCreationError
|
UserNoParent
|
NodeLookupFailed
NodeLookupError
|
HasParent
|
ManyParents
|
NegativeId
|
NotImplYet
|
NotImplYet
|
ManyNodeUsers
|
DoesNotExist
NodeId
|
NoContextFound
ContextId
|
NoContextFound
ContextId
|
NeedsConfiguration
|
NeedsConfiguration
|
NodeError
Text
|
NodeError
SomeException
|
QueryNoParse
Text
-- Left for backward compatibility, but we should remove them.
|
DoesNotExist
NodeId
instance
Prelude
.
Show
NodeError
instance
Prelude
.
Show
NodeError
where
where
...
@@ -46,18 +69,13 @@ instance Prelude.Show NodeError
...
@@ -46,18 +69,13 @@ instance Prelude.Show NodeError
show
NoCorpusFound
=
"No corpus found"
show
NoCorpusFound
=
"No corpus found"
show
(
NoUserFound
ur
)
=
"User("
<>
T
.
unpack
(
renderUser
ur
)
<>
") not found"
show
(
NoUserFound
ur
)
=
"User("
<>
T
.
unpack
(
renderUser
ur
)
<>
") not found"
show
MkNode
=
"Cannot make node"
show
(
NodeCreationFailed
reason
)
=
"Cannot make node due to: "
<>
T
.
unpack
(
renderNodeCreationFailed
reason
)
show
NegativeId
=
"Node with negative Id"
show
UserNoParent
=
"Should not have parent"
show
HasParent
=
"NodeType has parent"
show
NotImplYet
=
"Not implemented yet"
show
NotImplYet
=
"Not implemented yet"
show
ManyParents
=
"Too many parents"
show
(
NodeLookupFailed
reason
)
=
"Cannot lookup node due to: "
<>
T
.
unpack
(
renderNodeLookupFailed
reason
)
show
ManyNodeUsers
=
"Many userNode/user"
show
(
DoesNotExist
n
)
=
"Node does not exist ("
<>
show
n
<>
")"
show
(
NoContextFound
n
)
=
"Context node does not exist ("
<>
show
n
<>
")"
show
(
NoContextFound
n
)
=
"Context node does not exist ("
<>
show
n
<>
")"
show
NeedsConfiguration
=
"Needs configuration"
show
NeedsConfiguration
=
"Needs configuration"
show
(
NodeError
e
)
=
"NodeError: "
<>
cs
e
show
(
NodeError
e
)
=
"NodeError: "
<>
displayException
e
show
(
QueryNoParse
err
)
=
"QueryNoParse: "
<>
T
.
unpack
err
show
(
DoesNotExist
n
)
=
"Node does not exist ("
<>
show
n
<>
")"
instance
ToJSON
NodeError
where
instance
ToJSON
NodeError
where
toJSON
(
NoListFound
listId
)
=
toJSON
(
NoListFound
listId
)
=
...
@@ -72,7 +90,7 @@ class HasNodeError e where
...
@@ -72,7 +90,7 @@ class HasNodeError e where
errorWith
::
(
MonadError
e
m
errorWith
::
(
MonadError
e
m
,
HasNodeError
e
)
,
HasNodeError
e
)
=>
Text
->
m
a
=>
Text
->
m
a
errorWith
x
=
nodeError
(
NodeError
x
)
errorWith
x
=
nodeError
(
NodeError
$
toException
$
userError
$
T
.
unpack
x
)
nodeError
::
(
MonadError
e
m
nodeError
::
(
MonadError
e
m
,
HasNodeError
e
)
,
HasNodeError
e
)
...
...
src/Gargantext/Database/Query/Table/User.hs
View file @
3763d0dc
...
@@ -18,6 +18,7 @@ Functions to deal with users, database side.
...
@@ -18,6 +18,7 @@ Functions to deal with users, database side.
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE ViewPatterns #-}
module
Gargantext.Database.Query.Table.User
module
Gargantext.Database.Query.Table.User
(
insertUsers
(
insertUsers
...
@@ -57,9 +58,9 @@ import Gargantext.Core.Types.Individu
...
@@ -57,9 +58,9 @@ import Gargantext.Core.Types.Individu
import
Gargantext.Database.Admin.Config
(
nodeTypeId
)
import
Gargantext.Database.Admin.Config
(
nodeTypeId
)
import
Gargantext.Database.Admin.Types.Hyperdata
(
HyperdataUser
(
..
),
hu_pubmed_api_key
)
import
Gargantext.Database.Admin.Types.Hyperdata
(
HyperdataUser
(
..
),
hu_pubmed_api_key
)
import
Gargantext.Database.Admin.Types.Node
(
NodeType
(
NodeUser
),
Node
,
NodeId
(
..
),
pgNodeId
)
import
Gargantext.Database.Admin.Types.Node
(
NodeType
(
NodeUser
),
Node
,
NodeId
(
..
),
pgNodeId
)
import
Gargantext.Database.Query.Table.Node.Error
(
HasNodeError
)
import
Gargantext.Database.Admin.Types.Node
(
UserId
(
..
))
import
Gargantext.Database.Admin.Types.Node
(
UserId
(
..
))
import
Gargantext.Database.Prelude
import
Gargantext.Database.Prelude
import
Gargantext.Database.Query.Table.Node.Error
(
HasNodeError
)
import
Gargantext.Database.Query.Table.Node.UpdateOpaleye
(
updateNodeWithType
)
import
Gargantext.Database.Query.Table.Node.UpdateOpaleye
(
updateNodeWithType
)
import
Gargantext.Database.Schema.Node
(
NodeRead
,
node_hyperdata
,
queryNodeTable
,
node_id
,
node_user_id
,
node_typename
)
import
Gargantext.Database.Schema.Node
(
NodeRead
,
node_hyperdata
,
queryNodeTable
,
node_id
,
node_user_id
,
node_typename
)
import
Gargantext.Database.Schema.User
import
Gargantext.Database.Schema.User
...
@@ -67,11 +68,12 @@ import Gargantext.Prelude
...
@@ -67,11 +68,12 @@ import Gargantext.Prelude
import
Gargantext.Prelude.Crypto.Auth
qualified
as
Auth
import
Gargantext.Prelude.Crypto.Auth
qualified
as
Auth
import
Opaleye
import
Opaleye
import
PUBMED.Types
qualified
as
PUBMED
import
PUBMED.Types
qualified
as
PUBMED
import
qualified
Data.List.NonEmpty
as
NE
------------------------------------------------------------------------
------------------------------------------------------------------------
-- TODO: on conflict, nice message
-- TODO: on conflict, nice message
insertUsers
::
[
UserWrite
]
->
DBCmd
err
Int64
insertUsers
::
NonEmpty
UserWrite
->
DBCmd
err
Int64
insertUsers
us
=
mkCmd
$
\
c
->
runInsert
c
insert
insertUsers
(
NE
.
toList
->
us
)
=
mkCmd
$
\
c
->
runInsert
c
insert
where
where
insert
=
Insert
userTable
us
rCount
Nothing
insert
=
Insert
userTable
us
rCount
Nothing
...
@@ -302,7 +304,7 @@ getUser :: Username -> DBCmd err (Maybe UserLight)
...
@@ -302,7 +304,7 @@ getUser :: Username -> DBCmd err (Maybe UserLight)
getUser
u
=
userLightWithUsername
u
<$>
usersLight
getUser
u
=
userLightWithUsername
u
<$>
usersLight
----------------------------------------------------------------------
----------------------------------------------------------------------
insertNewUsers
::
[
NewUser
GargPassword
]
->
DBCmd
err
Int64
insertNewUsers
::
NonEmpty
(
NewUser
GargPassword
)
->
DBCmd
err
Int64
insertNewUsers
newUsers
=
do
insertNewUsers
newUsers
=
do
users'
<-
liftBase
$
mapM
toUserHash
newUsers
users'
<-
liftBase
$
mapM
toUserHash
newUsers
insertUsers
$
map
toUserWrite
users'
insertUsers
$
map
toUserWrite
users'
...
...
src/Gargantext/Database/Query/Tree/Root.hs
View file @
3763d0dc
...
@@ -37,7 +37,7 @@ getRootId :: (HasNodeError err) => User -> DBCmd err NodeId
...
@@ -37,7 +37,7 @@ getRootId :: (HasNodeError err) => User -> DBCmd err NodeId
getRootId
u
=
do
getRootId
u
=
do
maybeRoot
<-
head
<$>
getRoot
u
maybeRoot
<-
head
<$>
getRoot
u
case
maybeRoot
of
case
maybeRoot
of
Nothing
->
nodeError
$
NodeError
"[G.D.Q.T.R.getRootId] No root id"
Nothing
->
errorWith
"[G.D.Q.T.R.getRootId] No root id"
Just
r
->
pure
(
_node_id
r
)
Just
r
->
pure
(
_node_id
r
)
getRoot
::
User
->
DBCmd
err
[
Node
HyperdataUser
]
getRoot
::
User
->
DBCmd
err
[
Node
HyperdataUser
]
...
@@ -54,7 +54,7 @@ getOrMkRoot user = do
...
@@ -54,7 +54,7 @@ getOrMkRoot user = do
rootId''
<-
case
rootId'
of
rootId''
<-
case
rootId'
of
[]
->
mkRoot
user
[]
->
mkRoot
user
n
->
case
length
n
>=
2
of
n
->
case
length
n
>=
2
of
True
->
nodeError
ManyNodeUsers
True
->
nodeError
$
NodeLookupFailed
$
UserHasTooManyRoots
userId
n
False
->
pure
rootId'
False
->
pure
rootId'
rootId
<-
maybe
(
nodeError
NoRootFound
)
pure
(
head
rootId''
)
rootId
<-
maybe
(
nodeError
NoRootFound
)
pure
(
head
rootId''
)
...
@@ -80,7 +80,7 @@ getOrMk_RootWithCorpus user cName c = do
...
@@ -80,7 +80,7 @@ getOrMk_RootWithCorpus user cName c = do
else
do
else
do
c'
<-
mk
(
Just
$
fromLeft
"Default"
cName
)
c
rootId
userId
c'
<-
mk
(
Just
$
fromLeft
"Default"
cName
)
c
rootId
userId
_tId
<-
case
head
c'
of
_tId
<-
case
head
c'
of
Nothing
->
nodeError
$
NodeError
"[G.D.Q.T.Root.getOrMk...] mk Corpus failed"
Nothing
->
errorWith
"[G.D.Q.T.Root.getOrMk...] mk Corpus failed"
Just
c''
->
insertDefaultNode
NodeTexts
c''
userId
Just
c''
->
insertDefaultNode
NodeTexts
c''
userId
pure
c'
pure
c'
...
@@ -102,7 +102,7 @@ mkRoot user = do
...
@@ -102,7 +102,7 @@ mkRoot user = do
una
<-
getUsername
user
una
<-
getUsername
user
case
isPositive
uid
of
case
isPositive
uid
of
False
->
nodeError
NegativeId
False
->
nodeError
$
NodeCreationFailed
(
UserHasNegativeId
uid
)
True
->
do
True
->
do
rs
<-
mkNodeWithParent
NodeUser
Nothing
uid
una
rs
<-
mkNodeWithParent
NodeUser
Nothing
uid
una
_
<-
case
rs
of
_
<-
case
rs
of
...
@@ -135,4 +135,3 @@ selectRoot (RootId nid) =
...
@@ -135,4 +135,3 @@ selectRoot (RootId nid) =
restrict
-<
_node_typename
row
.==
(
sqlInt4
$
toDBid
NodeUser
)
restrict
-<
_node_typename
row
.==
(
sqlInt4
$
toDBid
NodeUser
)
restrict
-<
_node_id
row
.==
(
pgNodeId
nid
)
restrict
-<
_node_id
row
.==
(
pgNodeId
nid
)
returnA
-<
row
returnA
-<
row
selectRoot
UserPublic
=
panic
{-nodeError $ NodeError-}
"[G.D.Q.T.Root.selectRoot] No root for Public"
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment