2015-07-17 15:51:34 +08:00
package api
import (
2021-11-04 18:17:07 +08:00
"context"
2020-08-13 20:38:54 +08:00
"errors"
2015-07-21 18:18:11 +08:00
"fmt"
2021-11-29 17:18:01 +08:00
"net/http"
2022-07-08 19:07:00 +08:00
"strconv"
2022-11-14 20:11:26 +08:00
"strings"
2015-07-21 18:18:11 +08:00
2015-07-17 15:51:34 +08:00
"github.com/grafana/grafana/pkg/api/dtos"
2021-01-15 21:43:20 +08:00
"github.com/grafana/grafana/pkg/api/response"
2024-06-13 12:11:35 +08:00
"github.com/grafana/grafana/pkg/apimachinery/identity"
2015-07-20 23:46:48 +08:00
"github.com/grafana/grafana/pkg/events"
2019-02-24 06:35:26 +08:00
"github.com/grafana/grafana/pkg/infra/metrics"
2022-07-08 19:07:00 +08:00
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
2023-01-27 15:50:36 +08:00
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
2023-01-18 03:47:31 +08:00
"github.com/grafana/grafana/pkg/services/notifications"
2022-09-23 17:59:07 +08:00
"github.com/grafana/grafana/pkg/services/org"
2023-01-06 16:02:05 +08:00
tempuser "github.com/grafana/grafana/pkg/services/temp_user"
2022-06-28 20:32:25 +08:00
"github.com/grafana/grafana/pkg/services/user"
2015-07-18 23:39:12 +08:00
"github.com/grafana/grafana/pkg/setting"
2015-07-17 15:51:34 +08:00
"github.com/grafana/grafana/pkg/util"
2021-10-11 20:30:59 +08:00
"github.com/grafana/grafana/pkg/web"
2015-07-17 15:51:34 +08:00
)
2025-08-28 05:51:04 +08:00
// swagger:route GET /org/invites org invites getPendingOrgInvites
2022-07-27 21:54:37 +08:00
//
// Get pending invites.
//
// Responses:
// 200: getPendingOrgInvitesResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
2023-01-27 15:50:36 +08:00
func ( hs * HTTPServer ) GetPendingOrgInvites ( c * contextmodel . ReqContext ) response . Response {
2025-04-10 20:42:23 +08:00
query := tempuser . GetTempUsersQuery { OrgID : c . GetOrgID ( ) , Status : tempuser . TmpUserInvitePending }
2015-07-17 15:51:34 +08:00
2023-01-06 16:02:05 +08:00
queryResult , err := hs . tempUserService . GetTempUsersQuery ( c . Req . Context ( ) , & query )
if err != nil {
2023-08-09 18:33:35 +08:00
return response . Error ( http . StatusInternalServerError , "Failed to get invites from db" , err )
2015-07-17 15:51:34 +08:00
}
2023-01-06 16:02:05 +08:00
for _ , invite := range queryResult {
invite . URL = setting . ToAbsUrl ( "invite/" + invite . Code )
2015-07-20 20:26:49 +08:00
}
2023-01-06 16:02:05 +08:00
return response . JSON ( http . StatusOK , queryResult )
2015-07-17 15:51:34 +08:00
}
2025-08-28 05:51:04 +08:00
// swagger:route POST /org/invites org invites addOrgInvite
2022-07-27 21:54:37 +08:00
//
// Add invite.
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 412: SMTPNotEnabledError
// 500: internalServerError
2023-01-27 15:50:36 +08:00
func ( hs * HTTPServer ) AddOrgInvite ( c * contextmodel . ReqContext ) response . Response {
2021-11-29 17:18:01 +08:00
inviteDto := dtos . AddInviteForm { }
if err := web . Bind ( c . Req , & inviteDto ) ; err != nil {
return response . Error ( http . StatusBadRequest , "bad request data" , err )
}
2015-07-17 15:51:34 +08:00
if ! inviteDto . Role . IsValid ( ) {
2023-08-09 18:33:35 +08:00
return response . Error ( http . StatusBadRequest , "Invalid role specified" , nil )
2015-07-17 15:51:34 +08:00
}
2025-04-10 20:42:23 +08:00
if ! c . SignedInUser . GetOrgRole ( ) . Includes ( inviteDto . Role ) && ! c . GetIsGrafanaAdmin ( ) {
2022-06-28 00:40:12 +08:00
return response . Error ( http . StatusForbidden , "Cannot assign a role higher than user's role" , nil )
}
2015-07-17 15:51:34 +08:00
2015-07-18 17:43:34 +08:00
// first try get existing user
2022-08-04 19:22:43 +08:00
userQuery := user . GetUserByLoginQuery { LoginOrEmail : inviteDto . LoginOrEmail }
usr , err := hs . userService . GetByLogin ( c . Req . Context ( ) , & userQuery )
if err != nil {
2022-07-20 20:50:06 +08:00
if ! errors . Is ( err , user . ErrUserNotFound ) {
2023-08-09 18:33:35 +08:00
return response . Error ( http . StatusInternalServerError , "Failed to query db for existing user check" , err )
2015-07-18 17:43:34 +08:00
}
} else {
2022-07-08 19:07:00 +08:00
// Evaluate permissions for adding an existing user to the organization
2022-08-04 19:22:43 +08:00
userIDScope := ac . Scope ( "users" , "id" , strconv . Itoa ( int ( usr . ID ) ) )
2022-07-08 19:07:00 +08:00
hasAccess , err := hs . AccessControl . Evaluate ( c . Req . Context ( ) , c . SignedInUser , ac . EvalPermission ( ac . ActionOrgUsersAdd , userIDScope ) )
if err != nil {
return response . Error ( http . StatusInternalServerError , "Failed to evaluate permissions" , err )
}
if ! hasAccess {
return response . Error ( http . StatusForbidden , "Permission denied: not permitted to add an existing user to this organisation" , err )
}
2022-08-04 19:22:43 +08:00
return hs . inviteExistingUserToOrg ( c , usr , & inviteDto )
2015-07-18 17:43:34 +08:00
}
2023-02-27 22:28:49 +08:00
if hs . Cfg . DisableLoginForm {
2023-08-09 18:33:35 +08:00
return response . Error ( http . StatusBadRequest , "Cannot invite external user when login is disabled." , nil )
2019-09-13 00:45:50 +08:00
}
2023-01-06 16:02:05 +08:00
cmd := tempuser . CreateTempUserCommand { }
2025-04-10 20:42:23 +08:00
cmd . OrgID = c . GetOrgID ( )
2015-08-10 20:03:08 +08:00
cmd . Email = inviteDto . LoginOrEmail
2015-07-17 15:51:34 +08:00
cmd . Name = inviteDto . Name
2023-01-06 16:02:05 +08:00
cmd . Status = tempuser . TmpUserInvitePending
2023-08-09 18:33:35 +08:00
var userID int64
2025-04-10 20:42:23 +08:00
if id , err := identity . UserIdentifier ( c . GetID ( ) ) ; err == nil {
2024-08-09 23:20:24 +08:00
userID = id
2023-08-09 18:33:35 +08:00
}
cmd . InvitedByUserID = userID
2019-10-23 16:40:12 +08:00
cmd . Code , err = util . GetRandomString ( 30 )
if err != nil {
2023-08-09 18:33:35 +08:00
return response . Error ( http . StatusInternalServerError , "Could not generate random string" , err )
2019-10-23 16:40:12 +08:00
}
2015-07-17 20:42:49 +08:00
cmd . Role = inviteDto . Role
2022-12-13 22:33:05 +08:00
cmd . RemoteAddr = c . RemoteAddr ( )
2015-07-17 15:51:34 +08:00
2023-01-06 16:02:05 +08:00
cmdResult , err := hs . tempUserService . CreateTempUser ( c . Req . Context ( ) , & cmd )
if err != nil {
2023-08-09 18:33:35 +08:00
return response . Error ( http . StatusInternalServerError , "Failed to save invite to database" , err )
2015-07-17 15:51:34 +08:00
}
2015-07-18 23:39:12 +08:00
// send invite email
2017-12-13 20:16:44 +08:00
if inviteDto . SendEmail && util . IsEmail ( inviteDto . LoginOrEmail ) {
2023-01-18 03:47:31 +08:00
emailCmd := notifications . SendEmailCommand {
2015-08-10 20:03:08 +08:00
To : [ ] string { inviteDto . LoginOrEmail } ,
2021-07-19 18:31:51 +08:00
Template : "new_user_invite" ,
2023-08-30 23:46:47 +08:00
Data : map [ string ] any {
2015-08-11 16:35:10 +08:00
"Name" : util . StringsFallback2 ( cmd . Name , cmd . Email ) ,
2025-04-10 20:42:23 +08:00
"OrgName" : c . GetOrgName ( ) ,
"Email" : c . GetEmail ( ) ,
2015-08-11 16:35:10 +08:00
"LinkUrl" : setting . ToAbsUrl ( "invite/" + cmd . Code ) ,
2025-04-10 20:42:23 +08:00
"InvitedBy" : c . GetName ( ) ,
2015-07-18 23:39:12 +08:00
} ,
}
2022-02-01 00:24:52 +08:00
if err := hs . AlertNG . NotificationService . SendEmailCommandHandler ( c . Req . Context ( ) , & emailCmd ) ; err != nil {
2023-01-18 03:47:31 +08:00
if errors . Is ( err , notifications . ErrSmtpNotEnabled ) {
2023-08-09 18:33:35 +08:00
return response . Error ( http . StatusPreconditionFailed , err . Error ( ) , err )
2018-05-29 01:49:31 +08:00
}
2020-08-13 20:38:54 +08:00
2023-08-09 18:33:35 +08:00
return response . Error ( http . StatusInternalServerError , "Failed to send email invite" , err )
2015-07-18 23:39:12 +08:00
}
2015-08-10 20:03:08 +08:00
2023-01-06 16:02:05 +08:00
emailSentCmd := tempuser . UpdateTempUserWithEmailSentCommand { Code : cmdResult . Code }
2022-09-20 17:29:17 +08:00
if err := hs . tempUserService . UpdateTempUserWithEmailSent ( c . Req . Context ( ) , & emailSentCmd ) ; err != nil {
2023-08-09 18:33:35 +08:00
return response . Error ( http . StatusInternalServerError , "Failed to update invite with email sent info" , err )
2017-07-01 02:21:05 +08:00
}
2021-01-15 21:43:20 +08:00
return response . Success ( fmt . Sprintf ( "Sent invite to %s" , inviteDto . LoginOrEmail ) )
2015-07-18 23:39:12 +08:00
}
2021-01-15 21:43:20 +08:00
return response . Success ( fmt . Sprintf ( "Created invite for %s" , inviteDto . LoginOrEmail ) )
2015-07-17 15:51:34 +08:00
}
2015-07-20 16:57:39 +08:00
2023-01-27 15:50:36 +08:00
func ( hs * HTTPServer ) inviteExistingUserToOrg ( c * contextmodel . ReqContext , user * user . User , inviteDto * dtos . AddInviteForm ) response . Response {
2015-08-11 16:35:10 +08:00
// user exists, add org role
2025-04-10 20:42:23 +08:00
createOrgUserCmd := org . AddOrgUserCommand { OrgID : c . GetOrgID ( ) , UserID : user . ID , Role : inviteDto . Role }
2022-09-23 17:59:07 +08:00
if err := hs . orgService . AddOrgUser ( c . Req . Context ( ) , & createOrgUserCmd ) ; err != nil {
2023-01-09 21:39:53 +08:00
if errors . Is ( err , org . ErrOrgUserAlreadyAdded ) {
2023-08-09 18:33:35 +08:00
return response . Error ( http . StatusPreconditionFailed , fmt . Sprintf ( "User %s is already added to organization" , inviteDto . LoginOrEmail ) , err )
2015-08-11 16:35:10 +08:00
}
2023-08-09 18:33:35 +08:00
return response . Error ( http . StatusInternalServerError , "Error while trying to create org user" , err )
2018-03-22 19:37:35 +08:00
}
2015-08-11 16:35:10 +08:00
2018-03-22 19:37:35 +08:00
if inviteDto . SendEmail && util . IsEmail ( user . Email ) {
2023-01-18 03:47:31 +08:00
emailCmd := notifications . SendEmailCommand {
2018-03-22 19:37:35 +08:00
To : [ ] string { user . Email } ,
2021-07-19 18:31:51 +08:00
Template : "invited_to_org" ,
2023-08-30 23:46:47 +08:00
Data : map [ string ] any {
2018-03-22 19:37:35 +08:00
"Name" : user . NameOrFallback ( ) ,
2025-04-10 20:42:23 +08:00
"OrgName" : c . GetOrgName ( ) ,
"InvitedBy" : c . GetName ( ) ,
2018-03-22 19:37:35 +08:00
} ,
2015-08-11 16:35:10 +08:00
}
2022-02-01 00:24:52 +08:00
if err := hs . AlertNG . NotificationService . SendEmailCommandHandler ( c . Req . Context ( ) , & emailCmd ) ; err != nil {
2023-08-09 18:33:35 +08:00
return response . Error ( http . StatusInternalServerError , "Failed to send email invited_to_org" , err )
2018-03-22 19:37:35 +08:00
}
2015-08-11 16:35:10 +08:00
}
2018-03-22 19:37:35 +08:00
2022-04-15 20:01:58 +08:00
return response . JSON ( http . StatusOK , util . DynMap {
2025-04-10 20:42:23 +08:00
"message" : fmt . Sprintf ( "Existing Grafana user %s added to org %s" , user . NameOrFallback ( ) , c . GetOrgName ( ) ) ,
2022-06-28 20:32:25 +08:00
"userId" : user . ID ,
2020-09-14 14:58:23 +08:00
} )
2015-08-11 16:35:10 +08:00
}
2025-08-28 05:51:04 +08:00
// swagger:route DELETE /org/invites/{invitation_code}/revoke org invites revokeInvite
2022-07-27 21:54:37 +08:00
//
// Revoke invite.
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
2023-01-27 15:50:36 +08:00
func ( hs * HTTPServer ) RevokeInvite ( c * contextmodel . ReqContext ) response . Response {
2024-10-28 20:20:17 +08:00
query := tempuser . GetTempUserByCodeQuery { Code : web . Params ( c . Req ) [ ":code" ] }
queryResult , err := hs . tempUserService . GetTempUserByCode ( c . Req . Context ( ) , & query )
if err != nil {
if errors . Is ( err , tempuser . ErrTempUserNotFound ) {
return response . Error ( http . StatusNotFound , "Invite not found" , nil )
}
return response . Error ( http . StatusInternalServerError , "Failed to get invite" , err )
}
2025-04-10 20:42:23 +08:00
canRevoke := c . GetOrgID ( ) == queryResult . OrgID || c . GetIsGrafanaAdmin ( )
2024-10-28 20:20:17 +08:00
if ! canRevoke {
return response . Error ( http . StatusForbidden , "Permission denied: not permitted to revoke invite" , nil )
}
2023-01-06 16:02:05 +08:00
if ok , rsp := hs . updateTempUserStatus ( c . Req . Context ( ) , web . Params ( c . Req ) [ ":code" ] , tempuser . TmpUserRevoked ) ; ! ok {
2015-08-31 00:56:53 +08:00
return rsp
2015-07-20 16:57:39 +08:00
}
2021-01-15 21:43:20 +08:00
return response . Success ( "Invite revoked" )
2015-07-20 16:57:39 +08:00
}
2015-07-20 21:52:49 +08:00
2019-12-04 20:01:37 +08:00
// GetInviteInfoByCode gets a pending user invite corresponding to a certain code.
// A response containing an InviteInfo object is returned if the invite is found.
// If a (pending) invite is not found, 404 is returned.
2023-01-27 15:50:36 +08:00
func ( hs * HTTPServer ) GetInviteInfoByCode ( c * contextmodel . ReqContext ) response . Response {
2023-01-06 16:02:05 +08:00
query := tempuser . GetTempUserByCodeQuery { Code : web . Params ( c . Req ) [ ":code" ] }
queryResult , err := hs . tempUserService . GetTempUserByCode ( c . Req . Context ( ) , & query )
if err != nil {
if errors . Is ( err , tempuser . ErrTempUserNotFound ) {
2024-02-28 00:39:51 +08:00
return response . Error ( http . StatusNotFound , "Invite not found" , nil )
2015-07-20 21:52:49 +08:00
}
2024-02-28 00:39:51 +08:00
return response . Error ( http . StatusInternalServerError , "Failed to get invite" , err )
2015-07-20 21:52:49 +08:00
}
2023-01-06 16:02:05 +08:00
invite := queryResult
if invite . Status != tempuser . TmpUserInvitePending {
2024-02-28 00:39:51 +08:00
return response . Error ( http . StatusNotFound , "Invite not found" , nil )
2019-12-04 20:01:37 +08:00
}
2015-07-20 21:52:49 +08:00
2024-10-23 21:49:27 +08:00
orgResult , err := hs . orgService . GetByID ( c . Req . Context ( ) , & org . GetOrgByIDQuery {
ID : invite . OrgID ,
} )
if err != nil {
if errors . Is ( err , org . ErrOrgNotFound ) {
return response . Error ( http . StatusNotFound , "org not found" , nil )
}
return response . Error ( http . StatusInternalServerError , "Failed to get org" , err )
}
2022-04-15 20:01:58 +08:00
return response . JSON ( http . StatusOK , dtos . InviteInfo {
2015-08-10 19:46:59 +08:00
Email : invite . Email ,
Name : invite . Name ,
Username : invite . Email ,
InvitedBy : util . StringsFallback3 ( invite . InvitedByName , invite . InvitedByLogin , invite . InvitedByEmail ) ,
2024-10-23 21:49:27 +08:00
OrgName : orgResult . Name ,
2015-08-10 19:46:59 +08:00
} )
2015-07-20 21:52:49 +08:00
}
2015-07-20 23:46:48 +08:00
2023-01-27 15:50:36 +08:00
func ( hs * HTTPServer ) CompleteInvite ( c * contextmodel . ReqContext ) response . Response {
2021-11-29 17:18:01 +08:00
completeInvite := dtos . CompleteInviteForm { }
2022-11-14 20:11:26 +08:00
var err error
if err = web . Bind ( c . Req , & completeInvite ) ; err != nil {
2021-11-29 17:18:01 +08:00
return response . Error ( http . StatusBadRequest , "bad request data" , err )
}
2015-07-20 23:46:48 +08:00
2022-11-14 20:11:26 +08:00
completeInvite . Email , err = ValidateAndNormalizeEmail ( completeInvite . Email )
if err != nil {
return response . Error ( http . StatusBadRequest , "Invalid email address provided" , nil )
}
completeInvite . Username = strings . TrimSpace ( completeInvite . Username )
2023-01-06 16:02:05 +08:00
query := tempuser . GetTempUserByCodeQuery { Code : completeInvite . InviteCode }
queryResult , err := hs . tempUserService . GetTempUserByCode ( c . Req . Context ( ) , & query )
if err != nil {
if errors . Is ( err , tempuser . ErrTempUserNotFound ) {
2022-11-14 20:11:26 +08:00
return response . Error ( http . StatusNotFound , "Invite not found" , nil )
2015-07-20 23:46:48 +08:00
}
2022-11-14 20:11:26 +08:00
return response . Error ( http . StatusInternalServerError , "Failed to get invite" , err )
2015-07-20 23:46:48 +08:00
}
2023-01-06 16:02:05 +08:00
invite := queryResult
if invite . Status != tempuser . TmpUserInvitePending {
2022-11-14 20:11:26 +08:00
return response . Error ( http . StatusPreconditionFailed , fmt . Sprintf ( "Invite cannot be used in status %s" , invite . Status ) , nil )
}
// In case the user is invited by email address
if inviteMail , err := ValidateAndNormalizeEmail ( invite . Email ) ; err == nil {
// Make sure that the email address is not amended
if completeInvite . Email != inviteMail {
return response . Error ( http . StatusBadRequest , "The provided email is different from the address that is found in the invite" , nil )
}
2015-07-29 15:30:23 +08:00
}
2015-07-20 23:46:48 +08:00
2022-06-28 20:32:25 +08:00
cmd := user . CreateUserCommand {
2015-09-01 18:35:06 +08:00
Email : completeInvite . Email ,
Name : completeInvite . Name ,
Login : completeInvite . Username ,
Password : completeInvite . Password ,
SkipOrgSetup : true ,
2015-07-20 23:46:48 +08:00
}
2022-11-29 17:20:44 +08:00
usr , err := hs . userService . Create ( c . Req . Context ( ) , & cmd )
2021-03-19 00:16:56 +08:00
if err != nil {
2022-07-20 20:50:06 +08:00
if errors . Is ( err , user . ErrUserAlreadyExists ) {
2024-02-28 00:39:51 +08:00
return response . Error ( http . StatusPreconditionFailed , fmt . Sprintf ( "User with email '%s' or username '%s' already exists" , completeInvite . Email , completeInvite . Username ) , err )
2020-08-13 20:38:54 +08:00
}
2024-02-28 00:39:51 +08:00
return response . Error ( http . StatusInternalServerError , "failed to create user" , err )
2015-07-20 23:46:48 +08:00
}
2022-06-14 22:07:41 +08:00
if err := hs . bus . Publish ( c . Req . Context ( ) , & events . SignUpCompleted {
2022-06-28 20:32:25 +08:00
Name : usr . NameOrFallback ( ) ,
Email : usr . Email ,
2019-10-09 00:57:53 +08:00
} ) ; err != nil {
2024-02-28 00:39:51 +08:00
return response . Error ( http . StatusInternalServerError , "failed to publish event" , err )
2019-10-09 00:57:53 +08:00
}
2015-07-20 23:46:48 +08:00
2022-06-28 20:32:25 +08:00
if ok , rsp := hs . applyUserInvite ( c . Req . Context ( ) , usr , invite , true ) ; ! ok {
2015-08-31 00:56:53 +08:00
return rsp
}
2022-06-28 20:32:25 +08:00
err = hs . loginUserWithUser ( usr , c )
2020-03-23 20:37:53 +08:00
if err != nil {
2024-02-28 00:39:51 +08:00
return response . Error ( http . StatusInternalServerError , "failed to accept invite" , err )
2020-03-23 20:37:53 +08:00
}
2015-08-31 00:56:53 +08:00
2019-07-16 22:58:46 +08:00
metrics . MApiUserSignUpCompleted . Inc ( )
metrics . MApiUserSignUpInvite . Inc ( )
2015-08-31 00:56:53 +08:00
2022-04-15 20:01:58 +08:00
return response . JSON ( http . StatusOK , util . DynMap {
2020-09-07 23:06:11 +08:00
"message" : "User created and logged in" ,
2022-06-28 20:32:25 +08:00
"id" : usr . ID ,
2020-09-07 23:06:11 +08:00
} )
2015-08-31 00:56:53 +08:00
}
2023-01-06 16:02:05 +08:00
func ( hs * HTTPServer ) updateTempUserStatus ( ctx context . Context , code string , status tempuser . TempUserStatus ) ( bool , response . Response ) {
2015-08-31 00:56:53 +08:00
// update temp user status
2023-01-06 16:02:05 +08:00
updateTmpUserCmd := tempuser . UpdateTempUserStatusCommand { Code : code , Status : status }
2022-08-13 00:13:23 +08:00
if err := hs . tempUserService . UpdateTempUserStatus ( ctx , & updateTmpUserCmd ) ; err != nil {
2024-02-28 00:39:51 +08:00
return false , response . Error ( http . StatusInternalServerError , "Failed to update invite status" , err )
2015-08-31 00:56:53 +08:00
}
return true , nil
}
2023-01-06 16:02:05 +08:00
func ( hs * HTTPServer ) applyUserInvite ( ctx context . Context , usr * user . User , invite * tempuser . TempUserDTO , setActive bool ) ( bool , response . Response ) {
2015-08-11 16:45:03 +08:00
// add to org
2023-01-06 16:02:05 +08:00
addOrgUserCmd := org . AddOrgUserCommand { OrgID : invite . OrgID , UserID : usr . ID , Role : invite . Role }
2022-09-23 17:59:07 +08:00
if err := hs . orgService . AddOrgUser ( ctx , & addOrgUserCmd ) ; err != nil {
2023-01-09 21:39:53 +08:00
if ! errors . Is ( err , org . ErrOrgUserAlreadyAdded ) {
2024-02-28 00:39:51 +08:00
return false , response . Error ( http . StatusInternalServerError , "Error while trying to create org user" , err )
2015-08-17 16:55:52 +08:00
}
2015-08-11 16:45:03 +08:00
}
2015-07-20 23:46:48 +08:00
// update temp user status
2023-01-06 16:02:05 +08:00
if ok , rsp := hs . updateTempUserStatus ( ctx , invite . Code , tempuser . TmpUserCompleted ) ; ! ok {
2015-08-31 00:56:53 +08:00
return false , rsp
2015-07-20 23:46:48 +08:00
}
2015-08-31 00:56:53 +08:00
if setActive {
// set org to active
2024-04-29 14:53:05 +08:00
if err := hs . userService . Update ( ctx , & user . UpdateUserCommand { OrgID : & invite . OrgID , UserID : usr . ID } ) ; err != nil {
2024-02-28 00:39:51 +08:00
return false , response . Error ( http . StatusInternalServerError , "Failed to set org as active" , err )
2015-08-31 00:56:53 +08:00
}
}
2015-07-20 23:46:48 +08:00
2015-08-31 00:56:53 +08:00
return true , nil
2015-07-20 23:46:48 +08:00
}
2022-07-27 21:54:37 +08:00
2024-03-14 22:36:35 +08:00
// swagger:response SMTPNotEnabledError
type SMTPNotEnabledError PreconditionFailedError
2022-07-27 21:54:37 +08:00
// swagger:parameters addOrgInvite
type AddInviteParams struct {
// in:body
// required:true
Body dtos . AddInviteForm ` json:"body" `
}
// swagger:parameters revokeInvite
type RevokeInviteParams struct {
// in:path
// required:true
Code string ` json:"invitation_code" `
}
// swagger:response getPendingOrgInvitesResponse
type GetPendingOrgInvitesResponse struct {
// The response message
// in: body
2023-01-06 16:02:05 +08:00
Body [ ] * tempuser . TempUserDTO ` json:"body" `
2022-07-27 21:54:37 +08:00
}