mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-04-05 10:59:33 +00:00
Register external accounts
This creates the account if it doesn't exist yet; otherwise it's a noop. Only valid for non-local accounts.
This commit is contained in:
parent
aa099a340e
commit
7edb96a297
@ -0,0 +1,13 @@
|
||||
package docspell.backend.signup
|
||||
|
||||
import docspell.common._
|
||||
|
||||
final case class ExternalAccount(
|
||||
collName: Ident,
|
||||
login: Ident,
|
||||
source: AccountSource
|
||||
) {
|
||||
|
||||
def toAccountId: AccountId =
|
||||
AccountId(collName, login)
|
||||
}
|
@ -8,13 +8,11 @@ package docspell.backend.signup
|
||||
|
||||
import cats.effect.{Async, Resource}
|
||||
import cats.implicits._
|
||||
|
||||
import docspell.backend.PasswordCrypt
|
||||
import docspell.common._
|
||||
import docspell.common.syntax.all._
|
||||
import docspell.store.records.{RCollective, RInvitation, RUser}
|
||||
import docspell.store.{AddResult, Store}
|
||||
|
||||
import doobie.free.connection.ConnectionIO
|
||||
import org.log4s.getLogger
|
||||
|
||||
@ -22,6 +20,9 @@ trait OSignup[F[_]] {
|
||||
|
||||
def register(cfg: Config)(data: RegisterData): F[SignupResult]
|
||||
|
||||
/** Creates the given account if it doesn't exist. */
|
||||
def setupExternal(cfg: Config)(data: ExternalAccount): F[SignupResult]
|
||||
|
||||
def newInvite(cfg: Config)(password: Password): F[NewInviteResult]
|
||||
}
|
||||
|
||||
@ -76,6 +77,31 @@ object OSignup {
|
||||
}
|
||||
}
|
||||
|
||||
def setupExternal(cfg: Config)(data: ExternalAccount): F[SignupResult] =
|
||||
cfg.mode match {
|
||||
case Config.Mode.Closed =>
|
||||
SignupResult.signupClosed.pure[F]
|
||||
case _ =>
|
||||
if (data.source == AccountSource.Local)
|
||||
SignupResult.failure(new Exception("Account source must not be LOCAL!")).pure[F]
|
||||
else for {
|
||||
recs <- makeRecords(data.collName, data.login, Password(""), data.source)
|
||||
cres <- store.add(RCollective.insert(recs._1), RCollective.existsById(data.collName))
|
||||
ures <- store.add(RUser.insert(recs._2), RUser.exists(data.login))
|
||||
res = cres match {
|
||||
case AddResult.Failure(ex) =>
|
||||
SignupResult.failure(ex)
|
||||
case _ =>
|
||||
ures match {
|
||||
case AddResult.Failure(ex) =>
|
||||
SignupResult.failure(ex)
|
||||
case _ =>
|
||||
SignupResult.success
|
||||
}
|
||||
}
|
||||
} yield res
|
||||
}
|
||||
|
||||
private def retryInvite(res: SignupResult): Boolean =
|
||||
res match {
|
||||
case SignupResult.CollectiveExists =>
|
||||
@ -91,31 +117,6 @@ object OSignup {
|
||||
}
|
||||
|
||||
private def addUser(data: RegisterData): F[AddResult] = {
|
||||
def toRecords: F[(RCollective, RUser)] =
|
||||
for {
|
||||
id2 <- Ident.randomId[F]
|
||||
now <- Timestamp.current[F]
|
||||
c = RCollective(
|
||||
data.collName,
|
||||
CollectiveState.Active,
|
||||
Language.German,
|
||||
true,
|
||||
now
|
||||
)
|
||||
u = RUser(
|
||||
id2,
|
||||
data.login,
|
||||
data.collName,
|
||||
PasswordCrypt.crypt(data.password),
|
||||
UserState.Active,
|
||||
AccountSource.Local,
|
||||
None,
|
||||
0,
|
||||
None,
|
||||
now
|
||||
)
|
||||
} yield (c, u)
|
||||
|
||||
def insert(coll: RCollective, user: RUser): ConnectionIO[Int] =
|
||||
for {
|
||||
n1 <- RCollective.insert(coll)
|
||||
@ -127,9 +128,29 @@ object OSignup {
|
||||
|
||||
val msg = s"The collective '${data.collName}' already exists."
|
||||
for {
|
||||
cu <- toRecords
|
||||
cu <- makeRecords(data.collName, data.login, data.password, AccountSource.Local)
|
||||
save <- store.add(insert(cu._1, cu._2), collectiveExists)
|
||||
} yield save.fold(identity, _.withMsg(msg), identity)
|
||||
}
|
||||
|
||||
private def makeRecords(
|
||||
collName: Ident,
|
||||
login: Ident,
|
||||
password: Password,
|
||||
source: AccountSource
|
||||
): F[(RCollective, RUser)] =
|
||||
for {
|
||||
id2 <- Ident.randomId[F]
|
||||
now <- Timestamp.current[F]
|
||||
c = RCollective.makeDefault(collName, now)
|
||||
u = RUser.makeDefault(
|
||||
id2,
|
||||
login,
|
||||
collName,
|
||||
PasswordCrypt.crypt(password),
|
||||
source,
|
||||
now
|
||||
)
|
||||
} yield (c, u)
|
||||
})
|
||||
}
|
||||
|
@ -37,6 +37,9 @@ object RCollective {
|
||||
val all = NonEmptyList.of[Column[_]](id, state, language, integration, created)
|
||||
}
|
||||
|
||||
def makeDefault(collName: Ident, created: Timestamp): RCollective =
|
||||
RCollective(collName, CollectiveState.Active, Language.German, true, created)
|
||||
|
||||
val T = Table(None)
|
||||
def as(alias: String): Table =
|
||||
Table(Some(alias))
|
||||
|
@ -29,6 +29,28 @@ case class RUser(
|
||||
) {}
|
||||
|
||||
object RUser {
|
||||
|
||||
def makeDefault(
|
||||
id: Ident,
|
||||
login: Ident,
|
||||
collName: Ident,
|
||||
password: Password,
|
||||
source: AccountSource,
|
||||
created: Timestamp
|
||||
): RUser =
|
||||
RUser(
|
||||
id,
|
||||
login,
|
||||
collName,
|
||||
password,
|
||||
UserState.Active,
|
||||
source,
|
||||
None,
|
||||
0,
|
||||
None,
|
||||
created
|
||||
)
|
||||
|
||||
final case class Table(alias: Option[String]) extends TableDef {
|
||||
val tableName = "user_"
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user