mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	Oauth2 consumer (#679)
* initial stuff for oauth2 login, fails on: * login button on the signIn page to start the OAuth2 flow and a callback for each provider Only GitHub is implemented for now * show login button only when the OAuth2 consumer is configured (and activated) * create macaron group for oauth2 urls * prevent net/http in modules (other then oauth2) * use a new data sessions oauth2 folder for storing the oauth2 session data * add missing 2FA when this is enabled on the user * add password option for OAuth2 user , for use with git over http and login to the GUI * add tip for registering a GitHub OAuth application * at startup of Gitea register all configured providers and also on adding/deleting of new providers * custom handling of errors in oauth2 request init + show better tip * add ExternalLoginUser model and migration script to add it to database * link a external account to an existing account (still need to handle wrong login and signup) and remove if user is removed * remove the linked external account from the user his settings * if user is unknown we allow him to register a new account or link it to some existing account * sign up with button on signin page (als change OAuth2Provider structure so we can store basic stuff about providers) * from gorilla/sessions docs: "Important Note: If you aren't using gorilla/mux, you need to wrap your handlers with context.ClearHandler as or else you will leak memory!" (we're using gorilla/sessions for storing oauth2 sessions) * use updated goth lib that now supports getting the OAuth2 user if the AccessToken is still valid instead of re-authenticating (prevent flooding the OAuth2 provider)
This commit is contained in:
		
				
					committed by
					
						
						Kim "BKC" Carlbäcker
					
				
			
			
				
	
			
			
			
						parent
						
							fd941db246
						
					
				
				
					commit
					01d957677f
				
			@@ -142,6 +142,32 @@
 | 
			
		||||
							</div>
 | 
			
		||||
						{{end}}
 | 
			
		||||
 | 
			
		||||
						<!-- OAuth2 -->
 | 
			
		||||
						{{if .Source.IsOAuth2}}
 | 
			
		||||
							{{ $cfg:=.Source.OAuth2 }}
 | 
			
		||||
							<div class="inline required field">
 | 
			
		||||
								<label>{{.i18n.Tr "admin.auths.oauth2_provider"}}</label>
 | 
			
		||||
								<div class="ui selection type dropdown">
 | 
			
		||||
									<input type="hidden" id="oauth2_provider" name="oauth2_provider" value="{{$cfg.Provider}}" required>
 | 
			
		||||
									<div class="text">{{.CurrentOAuth2Provider.DisplayName}}</div>
 | 
			
		||||
									<i class="dropdown icon"></i>
 | 
			
		||||
									<div class="menu">
 | 
			
		||||
										{{range $key, $value := .OAuth2Providers}}
 | 
			
		||||
											<div class="item" data-value="{{$key}}">{{$value.DisplayName}}</div>
 | 
			
		||||
										{{end}}
 | 
			
		||||
									</div>
 | 
			
		||||
								</div>
 | 
			
		||||
							</div>
 | 
			
		||||
							<div class="required field">
 | 
			
		||||
								<label for="oauth2_key">{{.i18n.Tr "admin.auths.oauth2_clientID"}}</label>
 | 
			
		||||
								<input id="oauth2_key" name="oauth2_key" value="{{$cfg.ClientID}}" required>
 | 
			
		||||
							</div>
 | 
			
		||||
							<div class="required field">
 | 
			
		||||
								<label for="oauth2_secret">{{.i18n.Tr "admin.auths.oauth2_clientSecret"}}</label>
 | 
			
		||||
								<input id="oauth2_secret" name="oauth2_secret" value="{{$cfg.ClientSecret}}" required>
 | 
			
		||||
							</div>
 | 
			
		||||
						{{end}}
 | 
			
		||||
 | 
			
		||||
						<div class="inline field {{if not .Source.IsSMTP}}hide{{end}}">
 | 
			
		||||
							<div class="ui checkbox">
 | 
			
		||||
								<label><strong>{{.i18n.Tr "admin.auths.enable_tls"}}</strong></label>
 | 
			
		||||
 
 | 
			
		||||
@@ -133,6 +133,31 @@
 | 
			
		||||
							<input id="pam_service_name" name="pam_service_name" value="{{.pam_service_name}}" />
 | 
			
		||||
						</div>
 | 
			
		||||
 | 
			
		||||
						<!-- OAuth2 -->
 | 
			
		||||
						<div class="oauth2 field {{if not (eq .type 6)}}hide{{end}}">
 | 
			
		||||
							<div class="inline required field">
 | 
			
		||||
								<label>{{.i18n.Tr "admin.auths.oauth2_provider"}}</label>
 | 
			
		||||
								<div class="ui selection type dropdown">
 | 
			
		||||
									<input type="hidden" id="oauth2_provider" name="oauth2_provider" value="{{.oauth2_provider}}">
 | 
			
		||||
									<div class="text">{{.oauth2_provider}}</div>
 | 
			
		||||
									<i class="dropdown icon"></i>
 | 
			
		||||
									<div class="menu">
 | 
			
		||||
										{{range $key, $value := .OAuth2Providers}}
 | 
			
		||||
											<div class="item" data-value="{{$key}}">{{$value.DisplayName}}</div>
 | 
			
		||||
										{{end}}
 | 
			
		||||
									</div>
 | 
			
		||||
								</div>
 | 
			
		||||
							</div>
 | 
			
		||||
							<div class="required field">
 | 
			
		||||
								<label for="oauth2_key">{{.i18n.Tr "admin.auths.oauth2_clientID"}}</label>
 | 
			
		||||
								<input id="oauth2_key" name="oauth2_key" value="{{.oauth2_key}}">
 | 
			
		||||
							</div>
 | 
			
		||||
							<div class="required field">
 | 
			
		||||
								<label for="oauth2_secret">{{.i18n.Tr "admin.auths.oauth2_clientSecret"}}</label>
 | 
			
		||||
								<input id="oauth2_secret" name="oauth2_secret" value="{{.oauth2_secret}}">
 | 
			
		||||
							</div>
 | 
			
		||||
						</div>
 | 
			
		||||
 | 
			
		||||
						<div class="ldap field">
 | 
			
		||||
							<div class="ui checkbox">
 | 
			
		||||
								<label><strong>{{.i18n.Tr "admin.auths.attributes_in_bind"}}</strong></label>
 | 
			
		||||
@@ -170,6 +195,8 @@
 | 
			
		||||
				<div class="ui attached segment">
 | 
			
		||||
					<h5>GMail Settings:</h5>
 | 
			
		||||
					<p>Host: smtp.gmail.com, Port: 587, Enable TLS Encryption: true</p>
 | 
			
		||||
					<h5>OAuth GitHub:</h5>
 | 
			
		||||
					<p>{{.i18n.Tr "admin.auths.tip.github"}}</p>
 | 
			
		||||
				</div>
 | 
			
		||||
			</div>
 | 
			
		||||
		</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -43,7 +43,7 @@
 | 
			
		||||
							<input id="email" name="email" type="email" value="{{.User.Email}}" autofocus required>
 | 
			
		||||
						</div>
 | 
			
		||||
						<input class="fake" type="password">
 | 
			
		||||
						<div class="local field {{if .Err_Password}}error{{end}} {{if not (eq .User.LoginSource 0)}}hide{{end}}">
 | 
			
		||||
						<div class="local field {{if .Err_Password}}error{{end}} {{if not (or (.User.IsLocal) (.User.IsOAuth2))}}hide{{end}}">
 | 
			
		||||
							<label for="password">{{.i18n.Tr "password"}}</label>
 | 
			
		||||
							<input id="password" name="password" type="password">
 | 
			
		||||
							<p class="help">{{.i18n.Tr "admin.users.password_helper"}}</p>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								templates/user/auth/link_account.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								templates/user/auth/link_account.tmpl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
{{template "base/head" .}}
 | 
			
		||||
<div class="user link-account">
 | 
			
		||||
	<div class="ui middle very relaxed page grid">
 | 
			
		||||
		<div class="column">
 | 
			
		||||
			<p class="large center">
 | 
			
		||||
				{{.i18n.Tr "link_account_signin_or_signup"}}
 | 
			
		||||
			</p>
 | 
			
		||||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
</div>
 | 
			
		||||
{{template "user/auth/signin_inner" .}}
 | 
			
		||||
{{template "user/auth/signup_inner" .}}
 | 
			
		||||
{{template "base/footer" .}}
 | 
			
		||||
@@ -1,44 +1,3 @@
 | 
			
		||||
{{template "base/head" .}}
 | 
			
		||||
<div class="user signin">
 | 
			
		||||
	<div class="ui middle very relaxed page grid">
 | 
			
		||||
		<div class="column">
 | 
			
		||||
			<form class="ui form" action="{{.Link}}" method="post">
 | 
			
		||||
				{{.CsrfTokenHtml}}
 | 
			
		||||
				<h3 class="ui top attached header">
 | 
			
		||||
					{{.i18n.Tr "sign_in"}}
 | 
			
		||||
				</h3>
 | 
			
		||||
				<div class="ui attached segment">
 | 
			
		||||
					{{template "base/alert" .}}
 | 
			
		||||
					<div class="required inline field {{if .Err_UserName}}error{{end}}">
 | 
			
		||||
						<label for="user_name">{{.i18n.Tr "home.uname_holder"}}</label>
 | 
			
		||||
						<input id="user_name" name="user_name" value="{{.user_name}}" autofocus required>
 | 
			
		||||
					</div>
 | 
			
		||||
					<div class="required inline field {{if .Err_Password}}error{{end}}">
 | 
			
		||||
						<label for="password">{{.i18n.Tr "password"}}</label>
 | 
			
		||||
						<input id="password" name="password" type="password" value="{{.password}}" autocomplete="off" required>
 | 
			
		||||
					</div>
 | 
			
		||||
					<div class="inline field">
 | 
			
		||||
						<label></label>
 | 
			
		||||
						<div class="ui checkbox">
 | 
			
		||||
							<label>{{.i18n.Tr "auth.remember_me"}}</label>
 | 
			
		||||
							<input name="remember" type="checkbox">
 | 
			
		||||
						</div>
 | 
			
		||||
					</div>
 | 
			
		||||
 | 
			
		||||
					<div class="inline field">
 | 
			
		||||
						<label></label>
 | 
			
		||||
						<button class="ui green button">{{.i18n.Tr "sign_in"}}</button>
 | 
			
		||||
						<a href="{{AppSubUrl}}/user/forget_password">{{.i18n.Tr "auth.forget_password"}}</a>
 | 
			
		||||
					</div>
 | 
			
		||||
					{{if .ShowRegistrationButton}}
 | 
			
		||||
						<div class="inline field">
 | 
			
		||||
							<label></label>
 | 
			
		||||
							<a href="{{AppSubUrl}}/user/sign_up">{{.i18n.Tr "auth.sign_up_now" | Str2html}}</a>
 | 
			
		||||
						</div>
 | 
			
		||||
					{{end}}
 | 
			
		||||
				</div>
 | 
			
		||||
			</form>
 | 
			
		||||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
</div>
 | 
			
		||||
{{template "user/auth/signin_inner" .}}
 | 
			
		||||
{{template "base/footer" .}}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										57
									
								
								templates/user/auth/signin_inner.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								templates/user/auth/signin_inner.tmpl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
			
		||||
<div class="user signin{{if .LinkAccountMode}} icon{{end}}">
 | 
			
		||||
	<div class="ui middle very relaxed page grid">
 | 
			
		||||
		<div class="column">
 | 
			
		||||
			<form class="ui form" action="{{if not .LinkAccountMode}}{{.Link}}{{else}}{{.SignInLink}}{{end}}" method="post">
 | 
			
		||||
				{{.CsrfTokenHtml}}
 | 
			
		||||
				<h3 class="ui top attached header">
 | 
			
		||||
					{{.i18n.Tr "sign_in"}}
 | 
			
		||||
				</h3>
 | 
			
		||||
				<div class="ui attached segment">
 | 
			
		||||
					{{if or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeSignIn)}}
 | 
			
		||||
					{{template "base/alert" .}}
 | 
			
		||||
					{{end}}
 | 
			
		||||
					<div class="required inline field {{if and (.Err_UserName) (or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeSignIn))}}error{{end}}">
 | 
			
		||||
						<label for="user_name">{{.i18n.Tr "home.uname_holder"}}</label>
 | 
			
		||||
						<input id="user_name" name="user_name" value="{{.user_name}}" autofocus required>
 | 
			
		||||
					</div>
 | 
			
		||||
					<div class="required inline field {{if and (.Err_Password) (or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeSignIn))}}error{{end}}">
 | 
			
		||||
						<label for="password">{{.i18n.Tr "password"}}</label>
 | 
			
		||||
						<input id="password" name="password" type="password" value="{{.password}}" autocomplete="off" required>
 | 
			
		||||
					</div>
 | 
			
		||||
					{{if not .LinkAccountMode}}
 | 
			
		||||
					<div class="inline field">
 | 
			
		||||
						<label></label>
 | 
			
		||||
						<div class="ui checkbox">
 | 
			
		||||
							<label>{{.i18n.Tr "auth.remember_me"}}</label>
 | 
			
		||||
							<input name="remember" type="checkbox">
 | 
			
		||||
						</div>
 | 
			
		||||
					</div>
 | 
			
		||||
					{{end}}
 | 
			
		||||
 | 
			
		||||
					<div class="inline field">
 | 
			
		||||
						<label></label>
 | 
			
		||||
						<button class="ui green button">{{.i18n.Tr "sign_in"}}</button>
 | 
			
		||||
						<a href="{{AppSubUrl}}/user/forget_password">{{.i18n.Tr "auth.forget_password"}}</a>
 | 
			
		||||
					</div>
 | 
			
		||||
 | 
			
		||||
					{{if .ShowRegistrationButton}}
 | 
			
		||||
						<div class="inline field">
 | 
			
		||||
							<label></label>
 | 
			
		||||
							<a href="{{AppSubUrl}}/user/sign_up">{{.i18n.Tr "auth.sign_up_now" | Str2html}}</a>
 | 
			
		||||
						</div>
 | 
			
		||||
					{{end}}
 | 
			
		||||
 | 
			
		||||
					{{if .OAuth2Providers}}
 | 
			
		||||
					<div class="ui attached segment">
 | 
			
		||||
						<div class="oauth2 center">
 | 
			
		||||
							<div>
 | 
			
		||||
								<p>{{.i18n.Tr "sign_in_with"}}</p>{{range $key, $value := .OAuth2Providers}}<a href="{{AppSubUrl}}/user/oauth2/{{$key}}"><img alt="{{$value.DisplayName}}" title="{{$value.DisplayName}}" src="{{AppSubUrl}}{{$value.Image}}"></a>{{end}}
 | 
			
		||||
							</div>
 | 
			
		||||
						</div>
 | 
			
		||||
					</div>
 | 
			
		||||
					{{end}}
 | 
			
		||||
				</div>
 | 
			
		||||
			</form>
 | 
			
		||||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
</div>
 | 
			
		||||
@@ -1,56 +1,3 @@
 | 
			
		||||
{{template "base/head" .}}
 | 
			
		||||
<div class="user signup">
 | 
			
		||||
	<div class="ui middle very relaxed page grid">
 | 
			
		||||
		<div class="column">
 | 
			
		||||
			<form class="ui form" action="{{.Link}}" method="post">
 | 
			
		||||
				{{.CsrfTokenHtml}}
 | 
			
		||||
				<h3 class="ui top attached header">
 | 
			
		||||
					{{if .IsSocialLogin}}{{.i18n.Tr "social_sign_in" | Str2html}}{{else}}{{.i18n.Tr "sign_up"}}{{end}}
 | 
			
		||||
				</h3>
 | 
			
		||||
				<div class="ui attached segment">
 | 
			
		||||
					{{template "base/alert" .}}
 | 
			
		||||
					{{if .DisableRegistration}}
 | 
			
		||||
						<p>{{.i18n.Tr "auth.disable_register_prompt"}}</p>
 | 
			
		||||
					{{else}}
 | 
			
		||||
						<div class="required inline field {{if .Err_UserName}}error{{end}}">
 | 
			
		||||
							<label for="user_name">{{.i18n.Tr "username"}}</label>
 | 
			
		||||
							<input id="user_name" name="user_name" value="{{.user_name}}" autofocus required>
 | 
			
		||||
						</div>
 | 
			
		||||
						<div class="required inline field {{if .Err_Email}}error{{end}}">
 | 
			
		||||
							<label for="email">{{.i18n.Tr "email"}}</label>
 | 
			
		||||
							<input id="email" name="email" type="email" value="{{.email}}" required>
 | 
			
		||||
						</div>
 | 
			
		||||
						<div class="required inline field {{if .Err_Password}}error{{end}}">
 | 
			
		||||
							<label for="password">{{.i18n.Tr "password"}}</label>
 | 
			
		||||
							<input id="password" name="password" type="password" value="{{.password}}" autocomplete="off" required>
 | 
			
		||||
						</div>
 | 
			
		||||
						<div class="required inline field {{if .Err_Password}}error{{end}}">
 | 
			
		||||
							<label for="retype">{{.i18n.Tr "re_type"}}</label>
 | 
			
		||||
							<input id="retype" name="retype" type="password" value="{{.retype}}" autocomplete="off" required>
 | 
			
		||||
						</div>
 | 
			
		||||
						{{if .EnableCaptcha}}
 | 
			
		||||
							<div class="inline field">
 | 
			
		||||
								<label></label>
 | 
			
		||||
								{{.Captcha.CreateHtml}}
 | 
			
		||||
							</div>
 | 
			
		||||
							<div class="required inline field {{if .Err_Captcha}}error{{end}}">
 | 
			
		||||
								<label for="captcha">{{.i18n.Tr "captcha"}}</label>
 | 
			
		||||
								<input id="captcha" name="captcha" value="{{.captcha}}" autocomplete="off">
 | 
			
		||||
							</div>
 | 
			
		||||
						{{end}}
 | 
			
		||||
 | 
			
		||||
						<div class="inline field">
 | 
			
		||||
							<label></label>
 | 
			
		||||
							<button class="ui green button">{{.i18n.Tr "auth.create_new_account"}}</button>
 | 
			
		||||
						</div>
 | 
			
		||||
						<div class="inline field">
 | 
			
		||||
							<label></label>
 | 
			
		||||
							<a href="{{AppSubUrl}}/user/login">{{if .IsSocialLogin}}{{.i18n.Tr "auth.social_register_helper_msg"}}{{else}}{{.i18n.Tr "auth.register_helper_msg"}}{{end}}</a>
 | 
			
		||||
						</div>
 | 
			
		||||
					{{end}}
 | 
			
		||||
				</div>
 | 
			
		||||
			</form>
 | 
			
		||||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
</div>
 | 
			
		||||
{{template "user/auth/signup_inner" .}}
 | 
			
		||||
{{template "base/footer" .}}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										59
									
								
								templates/user/auth/signup_inner.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								templates/user/auth/signup_inner.tmpl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
			
		||||
<div class="user signup{{if .LinkAccountMode}} icon{{end}}">
 | 
			
		||||
	<div class="ui middle very relaxed page grid">
 | 
			
		||||
		<div class="column">
 | 
			
		||||
			<form class="ui form" action="{{if not .LinkAccountMode}}{{.Link}}{{else}}{{.SignUpLink}}{{end}}" method="post">
 | 
			
		||||
				{{.CsrfTokenHtml}}
 | 
			
		||||
				<h3 class="ui top attached header">
 | 
			
		||||
					{{.i18n.Tr "sign_up"}}
 | 
			
		||||
				</h3>
 | 
			
		||||
				<div class="ui attached segment">
 | 
			
		||||
					{{if or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeRegister)}}
 | 
			
		||||
					{{template "base/alert" .}}
 | 
			
		||||
					{{end}}
 | 
			
		||||
					{{if .DisableRegistration}}
 | 
			
		||||
						<p>{{.i18n.Tr "auth.disable_register_prompt"}}</p>
 | 
			
		||||
					{{else}}
 | 
			
		||||
						<div class="required inline field {{if and (.Err_UserName) (or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeRegister))}}error{{end}}">
 | 
			
		||||
							<label for="user_name">{{.i18n.Tr "username"}}</label>
 | 
			
		||||
							<input id="user_name" name="user_name" value="{{.user_name}}" autofocus required>
 | 
			
		||||
						</div>
 | 
			
		||||
						<div class="required inline field {{if .Err_Email}}error{{end}}">
 | 
			
		||||
							<label for="email">{{.i18n.Tr "email"}}</label>
 | 
			
		||||
							<input id="email" name="email" type="email" value="{{.email}}" required>
 | 
			
		||||
						</div>
 | 
			
		||||
						<div class="required inline field {{if and (.Err_Password) (or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeRegister))}}error{{end}}">
 | 
			
		||||
							<label for="password">{{.i18n.Tr "password"}}</label>
 | 
			
		||||
							<input id="password" name="password" type="password" value="{{.password}}" autocomplete="off" required>
 | 
			
		||||
						</div>
 | 
			
		||||
						<div class="required inline field {{if and (.Err_Password) (or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeRegister))}}error{{end}}">
 | 
			
		||||
							<label for="retype">{{.i18n.Tr "re_type"}}</label>
 | 
			
		||||
							<input id="retype" name="retype" type="password" value="{{.retype}}" autocomplete="off" required>
 | 
			
		||||
						</div>
 | 
			
		||||
						{{if .EnableCaptcha}}
 | 
			
		||||
							<div class="inline field">
 | 
			
		||||
								<label></label>
 | 
			
		||||
								{{.Captcha.CreateHtml}}
 | 
			
		||||
							</div>
 | 
			
		||||
							<div class="required inline field {{if .Err_Captcha}}error{{end}}">
 | 
			
		||||
								<label for="captcha">{{.i18n.Tr "captcha"}}</label>
 | 
			
		||||
								<input id="captcha" name="captcha" value="{{.captcha}}" autocomplete="off">
 | 
			
		||||
							</div>
 | 
			
		||||
						{{end}}
 | 
			
		||||
 | 
			
		||||
						<div class="inline field">
 | 
			
		||||
							<label></label>
 | 
			
		||||
							<button class="ui green button">{{.i18n.Tr "auth.create_new_account"}}</button>
 | 
			
		||||
						</div>
 | 
			
		||||
 | 
			
		||||
						{{if not .LinkAccountMode}}
 | 
			
		||||
						<div class="inline field">
 | 
			
		||||
							<label></label>
 | 
			
		||||
							<a href="{{AppSubUrl}}/user/login">{{.i18n.Tr "auth.register_helper_msg"}}</a>
 | 
			
		||||
						</div>
 | 
			
		||||
						{{end}}
 | 
			
		||||
					{{end}}
 | 
			
		||||
				</div>
 | 
			
		||||
			</form>
 | 
			
		||||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
</div>
 | 
			
		||||
							
								
								
									
										48
									
								
								templates/user/settings/account_link.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								templates/user/settings/account_link.tmpl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
			
		||||
{{template "base/head" .}}
 | 
			
		||||
<div class="user settings account_link">
 | 
			
		||||
	<div class="ui container">
 | 
			
		||||
		<div class="ui grid">
 | 
			
		||||
			{{template "user/settings/navbar" .}}
 | 
			
		||||
			<div class="twelve wide column content">
 | 
			
		||||
				{{template "base/alert" .}}
 | 
			
		||||
				<h4 class="ui top attached header">
 | 
			
		||||
					{{.i18n.Tr "settings.manage_account_links"}}
 | 
			
		||||
				</h4>
 | 
			
		||||
				<div class="ui attached segment">
 | 
			
		||||
					<div class="ui key list">
 | 
			
		||||
						<div class="item">
 | 
			
		||||
							{{.i18n.Tr "settings.manage_account_links_desc"}}
 | 
			
		||||
						</div>
 | 
			
		||||
						{{if .AccountLinks}}
 | 
			
		||||
						{{range $loginSource, $provider := .AccountLinks}}
 | 
			
		||||
							<div class="item ui grid">
 | 
			
		||||
								<div class="column">
 | 
			
		||||
									<strong>{{$provider}}</strong>
 | 
			
		||||
									{{if $loginSource.IsActived}}<span class="text red">{{$.i18n.Tr "settings.active"}}</span>{{end}}
 | 
			
		||||
									<div class="ui right">
 | 
			
		||||
										<button class="ui red tiny button delete-button" data-url="{{$.Link}}" data-id="{{$loginSource.ID}}">
 | 
			
		||||
											{{$.i18n.Tr "settings.delete_key"}}
 | 
			
		||||
										</button>
 | 
			
		||||
									</div>
 | 
			
		||||
								</div>
 | 
			
		||||
							</div>
 | 
			
		||||
						{{end}}
 | 
			
		||||
						{{end}}
 | 
			
		||||
					</div>
 | 
			
		||||
				</div>
 | 
			
		||||
			</div>
 | 
			
		||||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<div class="ui small basic delete modal">
 | 
			
		||||
	<div class="ui icon header">
 | 
			
		||||
		<i class="trash icon"></i>
 | 
			
		||||
		{{.i18n.Tr "settings.remove_account_link"}}
 | 
			
		||||
	</div>
 | 
			
		||||
	<div class="content">
 | 
			
		||||
		<p>{{.i18n.Tr "settings.remove_account_link_desc"}}</p>
 | 
			
		||||
	</div>
 | 
			
		||||
	{{template "base/delete_modal_actions" .}}
 | 
			
		||||
</div>
 | 
			
		||||
{{template "base/footer" .}}
 | 
			
		||||
@@ -22,6 +22,9 @@
 | 
			
		||||
		<a class="{{if .PageIsSettingsTwofa}}active{{end}} item" href="{{AppSubUrl}}/user/settings/two_factor">
 | 
			
		||||
			{{.i18n.Tr "settings.twofa"}}
 | 
			
		||||
		</a>
 | 
			
		||||
		<a class="{{if .PageIsSettingsAccountLink}}active{{end}} item" href="{{AppSubUrl}}/user/settings/account_link">
 | 
			
		||||
			{{.i18n.Tr "settings.account_link"}}
 | 
			
		||||
		</a>
 | 
			
		||||
		<a class="{{if .PageIsSettingsDelete}}active{{end}} item" href="{{AppSubUrl}}/user/settings/delete">
 | 
			
		||||
			{{.i18n.Tr "settings.delete"}}
 | 
			
		||||
		</a>
 | 
			
		||||
 
 | 
			
		||||
@@ -9,13 +9,15 @@
 | 
			
		||||
					{{.i18n.Tr "settings.change_password"}}
 | 
			
		||||
				</h4>
 | 
			
		||||
				<div class="ui attached segment">
 | 
			
		||||
					{{if .SignedUser.IsLocal}}
 | 
			
		||||
					{{if or (.SignedUser.IsLocal) (.SignedUser.IsOAuth2)}}
 | 
			
		||||
					<form class="ui form" action="{{.Link}}" method="post">
 | 
			
		||||
						{{.CsrfTokenHtml}}
 | 
			
		||||
						{{if .SignedUser.IsPasswordSet}}
 | 
			
		||||
						<div class="required field {{if .Err_OldPassword}}error{{end}}">
 | 
			
		||||
							<label for="old_password">{{.i18n.Tr "settings.old_password"}}</label>
 | 
			
		||||
							<input id="old_password" name="old_password" type="password" autocomplete="off" autofocus required>
 | 
			
		||||
						</div>
 | 
			
		||||
						{{end}}
 | 
			
		||||
						<div class="required field {{if .Err_Password}}error{{end}}">
 | 
			
		||||
							<label for="password">{{.i18n.Tr "settings.new_password"}}</label>
 | 
			
		||||
							<input id="password" name="password" type="password" autocomplete="off" required>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user