提交 fd26bb70 编写于 作者: m0_37741424's avatar m0_37741424

提交maxkey自定义扫码和社交服务绑定过程

上级 3ed7c987
......@@ -123,7 +123,7 @@ export class SocialsProviderComponent implements OnInit {
onAdd(e: MouseEvent): void {
e.preventDefault();
const modal = this.modalService.create({
//nzContent: SocialsProviderEditerComponent,
//nzContent: SocialsProviderBindUserComponent,
nzViewContainerRef: this.viewContainerRef,
nzComponentParams: {
isEdit: false,
......@@ -143,7 +143,7 @@ export class SocialsProviderComponent implements OnInit {
e.preventDefault();
const modal = this.modalService.create({
//nzContent: SocialsProviderEditerComponent,
//nzContent: SocialsProviderBindUserComponent,
nzViewContainerRef: this.viewContainerRef,
nzComponentParams: {
isEdit: true,
......
......@@ -14,13 +14,14 @@
* limitations under the License.
*/
import { Inject, Optional, Component, OnInit } from '@angular/core';
import { Inject, Optional, Component, OnInit, ViewContainerRef } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { ReuseTabService } from '@delon/abc/reuse-tab';
import { SettingsService } from '@delon/theme';
import { NzModalRef, NzModalService } from 'ng-zorro-antd/modal';
import { AuthnService } from '../../service/authn.service';
import { SocialsProviderService } from '../../service/socials-provider.service';
import {SocialsProviderBindUserComponent} from "./socials-provider-bind-user/socials-provider-bind-user.component";
@Component({
selector: 'app-callback',
......@@ -30,6 +31,8 @@ export class CallbackComponent implements OnInit {
provider = '';
constructor(
private viewContainerRef: ViewContainerRef,
private modalService: NzModalService,
private router: Router,
private socialsProviderService: SocialsProviderService,
private settingsService: SettingsService,
......@@ -50,6 +53,11 @@ export class CallbackComponent implements OnInit {
// 设置用户Token信息
this.authnService.auth(res.data);
}
else if (res.code === 102) {
//绑定用户
this.openBindUser(res.message)
return;
}
this.authnService.navigate({});
});
} else {
......@@ -60,4 +68,25 @@ export class CallbackComponent implements OnInit {
});
}
}
openBindUser(socialUserId: String) {
console.log("bind user : ",this.provider,socialUserId);
const modal = this.modalService.create({
nzContent: SocialsProviderBindUserComponent,
nzViewContainerRef: this.viewContainerRef,
nzComponentParams: {
socialUserId: socialUserId,
provider: this.provider
},
nzOnOk: () => new Promise(resolve => setTimeout(resolve, 1000))
});
// Return a result when closed
modal.afterClose.subscribe(result => {
if (result.refresh) {
}
});
}
}
......@@ -82,8 +82,11 @@
</nz-form-control>
</nz-form-item>
</div>
<div nz-row style="{{ loginType == 'qrscan' ? '' : 'display: none;' }}">
<div class="qrcode" id="div_qrcodelogin"> </div>
<div nz-row *ngIf="loginType=='qrscan'">
<div class="qrcode" id="div_qrcodelogin" style="background: #fff;padding: 20px;"> </div>
<div id="qrexpire" *ngIf="qrexpire" style="width: 100%;text-align: center;background: #fff;padding-bottom: 20px;">
二维码过期 <a href="javascript:" (click)="getQrCode()">刷新</a>
</div>
</div>
<nz-form-item *ngIf="loginType == 'normal' || loginType == 'mobile'">
<nz-col [nzSpan]="12">
......
@import '@delon/theme/index';
:host {
display: block;
width: 368px;
......@@ -81,4 +82,4 @@ input{
.qrcode iframe{
border: 0;
}
\ No newline at end of file
}
......@@ -31,6 +31,7 @@ import { ImageCaptchaService } from '../../../service/image-captcha.service';
import { SocialsProviderService } from '../../../service/socials-provider.service';
import { CONSTS } from '../../../shared/consts';
import { stringify } from 'querystring';
@Component({
......@@ -54,6 +55,7 @@ export class UserLoginComponent implements OnInit, OnDestroy {
loginType = 'normal';
loading = false;
passwordVisible = false;
qrexpire = false;
imageCaptcha = '';
captchaType = '';
state = '';
......@@ -287,6 +289,10 @@ export class UserLoginComponent implements OnInit, OnDestroy {
}
getQrCode(): void {
this.qrexpire = false;
if (this.interval$) {
clearInterval(this.interval$);
}
this.authnService.clearUser();
this.socialsProviderService.scanqrcode(this.socials.qrScan).subscribe(res => {
if (res.code === 0) {
......@@ -294,11 +300,14 @@ export class UserLoginComponent implements OnInit, OnDestroy {
this.qrScanWorkweixin(res.data);
} else if (this.socials.qrScan === 'dingtalk') {
this.qrScanDingtalk(res.data);
} else if (this.socials.qrScan === 'feishu') {
} else if (this.socials.qrScan === 'maxkey') {
this.qrScanMaxkey(res.data);
}else if (this.socials.qrScan === 'feishu') {
this.qrScanFeishu(res.data);
}
}
});
}
// #endregion
......@@ -364,4 +373,46 @@ export class UserLoginComponent implements OnInit, OnDestroy {
});
}
// #region QR Scan end
qrScanMaxkey(data: any) {
// @ts-ignore
document.getElementById("div_qrcodelogin").innerHTML='';
// @ts-ignore
var qrcode = new QRCode("div_qrcodelogin", {
width: 200,
height: 200,
colorDark : "#000000",
colorLight : "#ffffff"
}).makeCode(data.state);
//3分钟监听二维码
this.count = 90;
this.interval$ = setInterval(() => {
this.count -= 1;
if(this.loginType != 'qrscan') {
clearInterval(this.interval$);
}
if (this.count <= 0) {
clearInterval(this.interval$);
}
//轮询发送监听请求
this.socialsProviderService.qrcallback(this.socials.qrScan,data.state).subscribe(res => {
if (res.code === 0) {
// 清空路由复用信息
this.reuseTabService.clear();
// 设置用户Token信息
this.authnService.auth(res.data);
this.authnService.navigate({});
clearInterval(this.interval$);
} else if (res.code === 102) {
// 二维码过期
clearInterval(this.interval$);
this.qrexpire = true;
this.cdr.detectChanges();
} else if (res.code === 103) {
// 暂无用户扫码
}
});
this.cdr.detectChanges();
}, 2000);
}
}
......@@ -17,8 +17,8 @@
import { NgModule } from '@angular/core';
import { SharedModule } from '@shared';
import { NzStepsModule } from 'ng-zorro-antd/steps';
import { CallbackComponent } from './callback.component';
import { SocialsProviderBindUserComponent } from './socials-provider-bind-user/socials-provider-bind-user.component';
import { ForgotComponent } from './forgot/forgot.component';
import { UserLockComponent } from './lock/lock.component';
import { UserLoginComponent } from './login/login.component';
......@@ -26,7 +26,7 @@ import { PassportRoutingModule } from './passport-routing.module';
import { UserRegisterResultComponent } from './register-result/register-result.component';
import { UserRegisterComponent } from './register/register.component';
const COMPONENTS = [UserLoginComponent, UserRegisterResultComponent, UserRegisterComponent, UserLockComponent, CallbackComponent];
const COMPONENTS = [SocialsProviderBindUserComponent,UserLoginComponent, UserRegisterResultComponent, UserRegisterComponent, UserLockComponent, CallbackComponent];
@NgModule({
imports: [SharedModule, PassportRoutingModule, NzStepsModule],
......
<div *nzModalTitle>绑定</div>
<div>
<form nz-form [formGroup]="formGroup" (ngSubmit)="onSubmit($event)" se-container="1">
<nz-form-item style="width: 100%">
<nz-form-control nzErrorTip="Please input your telephone!">
<nz-input-group nzSize="large" nzPrefixIcon="user">
<input nz-input formControlName="telephone" placeholder="{{ 'mxk.login.text.mobile' | i18n }}" />
</nz-input-group>
</nz-form-control>
</nz-form-item>
<nz-form-item style="width: 100%">
<nz-form-control nzErrorTip="Please input your verification code!">
<nz-input-group nzSize="large" nzPrefixIcon="mail" nzSearch [nzAddOnAfter]="suffixSendOtpCodeButton">
<input nz-input formControlName="verificationCode" placeholder="{{ 'mxk.login.text.captcha' | i18n }}" />
</nz-input-group>
<ng-template #suffixSendOtpCodeButton>
<button type="button" nz-button nzSize="large" (click)="sendOtpCode()" [disabled]="count > 0" nzBlock [nzLoading]="loading">
{{ count ? count + 's' : ('app.register.get-verification-code' | i18n) }}
</button>
</ng-template>
</nz-form-control>
</nz-form-item>
</form>
</div>
<div *nzModalFooter>
<button nz-button nzType="default" (click)="onClose($event)">{{ 'mxk.text.close' | i18n }}</button>
<button nz-button nzType="primary" (click)="onSubmit($event)">{{ 'mxk.text.submit' | i18n }}</button>
</div>
/*
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SocialsProviderBindUserComponent } from './socials-provider-bind-user.component';
describe('SocialsProviderBindUserComponent', () => {
let component: SocialsProviderBindUserComponent;
let fixture: ComponentFixture<SocialsProviderBindUserComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ SocialsProviderBindUserComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(SocialsProviderBindUserComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
/*
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Component, ChangeDetectorRef, Input, OnInit, Inject } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { I18NService } from '@core';
import { _HttpClient, ALAIN_I18N_TOKEN, SettingsService } from '@delon/theme';
import format from 'date-fns/format';
import { NzMessageService } from 'ng-zorro-antd/message';
import { NzModalRef, NzModalService } from 'ng-zorro-antd/modal';
import { AuthnService } from "../../../service/authn.service";
import { SocialsProviderService } from "../../../service/socials-provider.service";
import { ReuseTabService } from "@delon/abc/reuse-tab";
@Component({
selector: 'app-socials-provider-binduser',
templateUrl: './socials-provider-bind-user.component.html',
styles: [
`
nz-form-item {
width: 100%;
}
`
],
styleUrls: ['./socials-provider-bind-user.component.less']
})
export class SocialsProviderBindUserComponent implements OnInit {
@Input() socialUserId?: String;
@Input() provider?: String;
loading = false;
count = 0;
formGroup: FormGroup = new FormGroup({});
interval$: any;
constructor(
private modalRef: NzModalRef,
private fb: FormBuilder,
private authnService: AuthnService,
private msg: NzMessageService,
private socialsProviderService: SocialsProviderService,
@Inject(ALAIN_I18N_TOKEN) private i18n: I18NService,
@Inject(ReuseTabService)
private reuseTabService: ReuseTabService,
private cdr: ChangeDetectorRef
) {}
ngOnInit(): void {
this.formGroup = this.fb.group({
telephone: [null, [Validators.required]],
verificationCode: [null, [Validators.required]]
});
console.log("bind open form : ",this.provider,this.socialUserId)
}
onClose(e: MouseEvent): void {
e.preventDefault();
this.modalRef.destroy({ refresh: false });
}
onSubmit(e: MouseEvent): void {
console.log("this.formGroup.valid",this.formGroup.valid)
//表单验证
if (this.formGroup.valid) {
let request = {
username: this.socialUserId,
mobile: this.formGroup.get('telephone')?.value,
code: this.formGroup.get('verificationCode')?.value,
authType: this.provider
}
this.authnService.bindSocialsUser(request).subscribe(res => {
if (res.code === 0) {
// 清空路由复用信息
this.reuseTabService.clear();
// 设置用户Token信息
this.authnService.auth(res.data);
this.authnService.navigate({});
} else {
this.msg.error(`绑定失败`);
}
});
} else {
Object.values(this.formGroup.controls).forEach(control => {
if (control.invalid) {
control.markAsDirty();
control.updateValueAndValidity({ onlySelf: true });
}
});
}
e.preventDefault();
}
sendOtpCode(): void {
this.authnService.produceOtp({ mobile:this.formGroup.get('telephone')?.value}).subscribe(res => {
if (res.code !== 0) {
this.msg.error(`发送失败`);
}else {
this.msg.success(`发送成功`);
}
});
this.count = 59;
this.interval$ = setInterval(() => {
this.count -= 1;
if (this.count <= 0) {
clearInterval(this.interval$);
}
this.cdr.detectChanges();
}, 1000);
}
}
......@@ -61,6 +61,10 @@ export class AuthnService {
return this.http.post('/login/signin?_allow_anonymous=true', authParam);
}
bindSocialsUser(authParam: any) {
return this.http.post('/login/signin/bindusersocials?_allow_anonymous=true', authParam);
}
//退出
logout() {
this.cookieService.delete(CONSTS.CONGRESS, '/');
......
......@@ -43,7 +43,15 @@ export class SocialsProviderService extends BaseService<SocialsProvider> {
return this.getByParams(params, `/logon/oauth20/callback/${provider}?_allow_anonymous=true`);
}
bindUser(provider: string, params: NzSafeAny): Observable<Message<SocialsProvider>> {
return this.getByParams(params, `/logon/oauth20/binduser/${provider}?_allow_anonymous=true`);
}
bind(provider: string, params: NzSafeAny): Observable<Message<SocialsProvider>> {
return this.getByParams(params, `/logon/oauth20/bind/${provider}?_allow_anonymous=true`);
}
qrcallback(provider: string, token: string ): Observable<Message<SocialsProvider>> {
return this.getByParams({}, `/logon/oauth20/qrcallback/${provider}/${token}?_allow_anonymous=true`);
}
}
......@@ -27,7 +27,7 @@ export const environment = {
production: false,
useHash: true,
api: {
baseUrl: 'http://sso.maxkey.top:9527/sign/',
baseUrl: '/sign/',
refreshTokenEnabled: true,
refreshTokenType: 're-request'
},
......
......@@ -27,6 +27,7 @@
<meta http-equiv="description" content="MaxKey Single Sign-On">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<script src="./assets/transform.js"></script>
<script src="./assets/qrcode/qrcode.min.js"></script>
<!-- Apple Touch Icon -->
<!-- <link rel="apple-touch-icon" href="custom-icon.png"> -->
<style type="text/css">
......@@ -142,9 +143,9 @@
</div>
</body>
<!--attention http or https-->
<!--企业微信
--企业微信
<script src="http://wwcdn.weixin.qq.com/node/wework/wwopen/js/wwLogin-1.2.7.js"></script>
-->
<!--钉钉-->
<!---->
<script src="http://g.alicdn.com/dingding/dinglogin/0.0.5/ddLogin.js"></script>
......@@ -191,4 +192,4 @@
</script>
-->
</html>
\ No newline at end of file
</html>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册