Browse Source
feat: login with pair code (#171)
feat: login with pair code (#171)
* feat: wip pair code login feat(app): add LoginWithCode method to IAppService interface for handling phone number login feat(app): implement LoginWithCode method in App struct to handle phone number login logic feat(app): implement LoginWithCode method in serviceApp to pair phone number with WhatsApp client * feat: add api login with code * feat: add ui getting pair code * feat: add pair code * chore: update docs & text * feat: upgrade version * chore: update docs * feat: update image gallery * fix: show error message * chore: update repo * fix: some code improvementpull/181/head v4.16.0
committed by
GitHub
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 327 additions and 38 deletions
-
4docker/golang.Dockerfile
-
43docs/openapi.yaml
-
52readme.md
-
2src/config/settings.go
-
1src/domains/app/app.go
-
8src/go.mod
-
8src/go.sum
-
15src/internal/rest/app.go
-
2src/pkg/error/app_error.go
-
23src/services/app.go
-
21src/validations/app_validation.go
-
61src/validations/app_validation_test.go
-
7src/views/components/AppLogin.js
-
109src/views/components/AppLoginWithCode.js
-
3src/views/components/AppReconnect.js
-
6src/views/index.html
@ -0,0 +1,21 @@ |
|||
package validations |
|||
|
|||
import ( |
|||
"context" |
|||
"fmt" |
|||
pkgError "github.com/aldinokemal/go-whatsapp-web-multidevice/pkg/error" |
|||
validation "github.com/go-ozzo/ozzo-validation/v4" |
|||
"regexp" |
|||
) |
|||
|
|||
func ValidateLoginWithCode(ctx context.Context, phoneNumber string) error { |
|||
// Combine validations using a single ValidateWithContext call
|
|||
err := validation.ValidateWithContext(ctx, &phoneNumber, |
|||
validation.Required, |
|||
validation.Match(regexp.MustCompile(`^\+?[0-9]{1,15}$`)), |
|||
) |
|||
if err != nil { |
|||
return pkgError.ValidationError(fmt.Sprintf("phone_number(%s): %s", phoneNumber, err.Error())) |
|||
} |
|||
return nil |
|||
} |
|||
@ -0,0 +1,61 @@ |
|||
package validations |
|||
|
|||
import ( |
|||
"context" |
|||
"testing" |
|||
) |
|||
|
|||
func TestValidateLoginWithCode(t *testing.T) { |
|||
type args struct { |
|||
phoneNumber string |
|||
} |
|||
tests := []struct { |
|||
name string |
|||
args args |
|||
wantErr bool |
|||
}{ |
|||
{ |
|||
name: "Phone with +", |
|||
args: args{phoneNumber: "+6281234567890"}, |
|||
wantErr: false, |
|||
}, |
|||
{ |
|||
name: "Phone without +", |
|||
args: args{phoneNumber: "621234567890"}, |
|||
wantErr: false, |
|||
}, |
|||
{ |
|||
name: "Phone with 0", |
|||
args: args{phoneNumber: "081234567890"}, |
|||
wantErr: false, |
|||
}, |
|||
{ |
|||
name: "Phone contains alphabet", |
|||
args: args{phoneNumber: "+6281234567890a"}, |
|||
wantErr: true, |
|||
}, |
|||
{ |
|||
name: "Empty phone number", |
|||
args: args{phoneNumber: ""}, |
|||
wantErr: true, |
|||
}, |
|||
{ |
|||
name: "Phone with special characters", |
|||
args: args{phoneNumber: "+6281234567890!@#"}, |
|||
wantErr: true, |
|||
}, |
|||
{ |
|||
name: "Extremely long phone number", |
|||
args: args{phoneNumber: "+62812345678901234567890"}, |
|||
wantErr: true, |
|||
}, |
|||
} |
|||
|
|||
for _, tt := range tests { |
|||
t.Run(tt.name, func(t *testing.T) { |
|||
if err := ValidateLoginWithCode(context.Background(), tt.args.phoneNumber); (err != nil) != tt.wantErr { |
|||
t.Errorf("ValidateLoginWithCode() error = %v, wantErr %v", err, tt.wantErr) |
|||
} |
|||
}) |
|||
} |
|||
} |
|||
@ -0,0 +1,109 @@ |
|||
export default { |
|||
name: 'AppLoginWithCode', |
|||
props: { |
|||
connected: { |
|||
type: Boolean, |
|||
default: false, |
|||
} |
|||
}, |
|||
watch: { |
|||
connected: function(val) { |
|||
if (val) { |
|||
// reset form
|
|||
this.phone = ''; |
|||
this.pair_code = null; |
|||
|
|||
$('#modalLoginWithCode').modal('hide'); |
|||
} |
|||
}, |
|||
}, |
|||
data: () => { |
|||
return { |
|||
phone: '', |
|||
submitting: false, |
|||
pair_code: null, |
|||
}; |
|||
}, |
|||
methods: { |
|||
async openModal() { |
|||
try { |
|||
if (this.connected) throw Error('You are already logged in.'); |
|||
|
|||
$('#modalLoginWithCode').modal({ |
|||
onApprove: function() { |
|||
return false; |
|||
}, |
|||
}).modal('show'); |
|||
} catch (err) { |
|||
showErrorInfo(err); |
|||
} |
|||
}, |
|||
async handleSubmit() { |
|||
if (this.submitting) return; |
|||
try { |
|||
this.submitting = true; |
|||
const { data } = await http.get(`/app/login-with-code`, { |
|||
params: { |
|||
phone: this.phone, |
|||
}, |
|||
}); |
|||
this.pair_code = data.results.pair_code; |
|||
} catch (err) { |
|||
if (err.response) { |
|||
showErrorInfo(err.response.data.message); |
|||
}else{ |
|||
showErrorInfo(err.message); |
|||
} |
|||
} finally { |
|||
this.submitting = false; |
|||
} |
|||
}, |
|||
}, |
|||
template: `
|
|||
<div class="green card" @click="openModal" style="cursor: pointer"> |
|||
<div class="content"> |
|||
<div class="header">Login with Code</div> |
|||
<div class="description"> |
|||
Enter your pairing code to log in and access your devices. |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- Modal Login --> |
|||
<div class="ui small modal" id="modalLoginWithCode"> |
|||
<i class="close icon"></i> |
|||
<div class="header"> |
|||
Getting Pair Code |
|||
</div> |
|||
<div class="content"> |
|||
<div class="ui message info"> |
|||
<div class="header">How to pair?</div> |
|||
<ol> |
|||
<li>Open your Whatsapp</li> |
|||
<li>Link a device</li> |
|||
<li>Link with pair code</li> |
|||
</ol> |
|||
</div> |
|||
|
|||
<div class="ui form"> |
|||
<div class="field"> |
|||
<label>Phone</label> |
|||
<input type="text" v-model="phone" placeholder="Type your phone number" |
|||
@keyup.enter="handleSubmit" :disabled="submitting"> |
|||
<small>Enter to submit</small> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="ui grid" v-if="pair_code"> |
|||
<div class="ui two column centered grid"> |
|||
<div class="column center aligned"> |
|||
<div class="header">Pair Code</div> |
|||
<p style="font-size: 32px">{{ pair_code }}</p> |
|||
|
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
`,
|
|||
}; |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue