मान लीजिए कि आप एक छोटे संगठन या क्लब को प्रबंधित करने में मदद करते हैं और आपके पास सभी सदस्यों के विवरण (नाम, फोन, ईमेल...) संग्रहीत करने वाला एक डेटाबेस है।
क्या यह अच्छा नहीं होगा कि आपको यह अद्यतन जानकारी हर उस जगह उपलब्ध हो जिसकी आपको आवश्यकता है? खैर, कार्डडीएवी के साथ आप यह कर सकते हैं!
कार्डडीएवी संपर्क प्रबंधन के लिए एक अच्छी तरह से समर्थित खुला मानक है; इसका iOS संपर्क ऐप और Android के लिए उपलब्ध कई ऐप्स में एक मूल एकीकरण है।
सर्वर-साइड, कार्डडीएवी को लागू करना एक http-सर्वर है जो असामान्य http-विधियों (PROPFIND, GET के बजाय रिपोर्ट, पोस्ट...) पर प्रतिक्रिया करता है। सौभाग्य से काम को बहुत सरल बनाने के लिए एक गो मॉड्यूल मौजूद है: github.com/emersion/go-webdav। यह लाइब्रेरी एक कार्यान्वित बैकएंड की अपेक्षा करती है और एक मानक http.Handler प्रदान करती है जिसे प्रमाणीकरण के बाद HTTP अनुरोधों को पूरा करना चाहिए।
दिलचस्प बात यह है कि लाइब्रेरी उपयोगकर्ता प्रमाणीकरण के संबंध में कोई सहायता प्रदान नहीं करती है, हालांकि गो कंपोज़बिलिटी के लिए धन्यवाद, यह कोई मुद्दा नहीं है।
कार्डडीएवी बेसिक ऑथ क्रेडेंशियल्स का उपयोग करता है। एक बार क्रेडेंशियल्स की जांच हो जाने के बाद, हम उन क्रेडेंशियल्स को संदर्भ में सहेज सकते हैं (बाद में उपयोगी होंगे):
package main import ( "context" "net/http" "github.com/emersion/go-webdav/carddav" ) type ( ctxKey struct{} ctxValue struct { username string } ) func NewCardDAVHandler() http.Handler { actualHandler := carddav.Handler{ Backend: &ownBackend{}, } return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { username, password, ok := r.BasicAuth() // check username and password: adjust the logic to your system (do NOT store passwords in plaintext) if !ok || username != "admin" || password != "s3cr3t" { // abort the request handling on failure w.Header().Add("WWW-Authenticate", `Basic realm="Please authenticate", charset="UTF-8"`) http.Error(w, "HTTP Basic auth is required", http.StatusUnauthorized) return } // user is authenticated: store this info in the context ctx := context.WithValue(r.Context(), ctxKey{}, ctxValue{username}) // delegate the work to the CardDAV handle actualHandler.ServeHTTP(w, r.WithContext(ctx)) }) }
ownBackend संरचना को कार्डडेव.बैकएंड इंटरफ़ेस लागू करना होगा, जो बहुत पतला नहीं है, लेकिन फिर भी प्रबंधनीय है।
करंटयूजरप्रिंसिपल और एड्रेसबुकहोमसेटपाथ को यूआरएल (स्लैश से शुरू और खत्म) प्रदान करना होगा। आमतौर पर यह उपयोगकर्ता नाम/संपर्क होगा. यह वह जगह है जहां आपको संदर्भ से उपयोगकर्ता नाम निकालने की आवश्यकता है (जो एकमात्र उपलब्ध तर्क है):
func currentUsername(ctx context.Context) (string, error) { if v, ok := ctx.Value(ctxKey{}).(ctxValue); ok { return v.username, nil } return "", errors.New("not authenticated") } type ownBackend struct{} // must begin and end with a slash func (b *ownBackend) CurrentUserPrincipal(ctx context.Context) (string, error) { username, err := currentUsername(ctx) return "/" url.PathEscape(username) "/", err } // must begin and end with a slash as well func (b *ownBackend) AddressBookHomeSetPath(ctx context.Context) (string, error) { principal, err := b.CurrentUserPrincipal(ctx) return principal "contacts/", err }
उसके बाद मज़ा शुरू हो सकता है: आपको एड्रेसबुक, गेटएड्रेसऑब्जेक्ट और लिस्टएड्रेसऑब्जेक्ट्स विधियों को लागू करने की आवश्यकता है।
एड्रेसबुक एक सरल संरचना लौटाता है, जहां पथ ऊपर दिए गए एड्रेसबुकहोमसेटपाथ से शुरू होना चाहिए (और एक स्लैश के साथ समाप्त होना चाहिए)
GetAddressObject और ListAddressObjects को वर्तमान पथ की जांच करनी चाहिए (यह सुनिश्चित करने के लिए कि वर्तमान में प्रमाणित उपयोगकर्ता उन संपर्कों तक पहुंच सकता है) और फिर संपर्कों को एड्रेसऑब्जेक्ट के रूप में लौटाएं।
एड्रेसऑब्जेक्ट में कई विशेषताएं हैं, सबसे महत्वपूर्ण:
वीकार्ड वास्तविक संपर्क डेटा का प्रतिनिधित्व करता है और संभवतः आप अपने संपर्कों को कैसे संग्रहीत करते हैं इसके आधार पर इसे अनुकूलित किया जाना चाहिए। मेरे मामले में, यह इस तरह समाप्त हुआ:
func utf8Field(v string) *vcard.Field { return &vcard.Field{ Value: v, Params: vcard.Params{ "CHARSET": []string{"UTF-8"}, }, } } func vcardFromUser(u graphqlient.User) vcard.Card { c := vcard.Card{} c.Set(vcard.FieldFormattedName, utf8Field(u.Firstname " " u.Lastname)) c.SetName(&vcard.Name{ Field: utf8Field(""), FamilyName: u.Lastname, GivenName: u.Firstname, }) c.SetRevision(u.UpdatedAt) c.SetValue(vcard.FieldUID, u.Extid) c.Set(vcard.FieldOrganization, utf8Field(u.Unit)) // addFields sorts the key to ensure a stable order addFields := func(fieldName string, values map[string]string) { for _, k := range slices.Sorted(maps.Keys(values)) { v := values[k] c.Add(fieldName, &vcard.Field{ Value: v, Params: vcard.Params{ vcard.ParamType: []string{k ";CHARSET=UTF-8"}, // hacky but prevent maps ordering issues // "CHARSET": []string{"UTF-8"}, }, }) } } addFields(vcard.FieldEmail, u.Emails) addFields(vcard.FieldTelephone, u.Phones) vcard.ToV4(c) return c }
कुछ विधियां किसी संपर्क को अपडेट करने की अनुमति देती हैं। चूँकि मैं नहीं चाहता कि मेरी सदस्य सूची को कार्डडीएवी के माध्यम से अपडेट किया जाए, मैं पुट और डिलीट तरीकों में 403 त्रुटि लौटाता हूँ: return webdav.NewHTTPError(http.StatusForbidden,Errors.New("carddav: कार्रवाई समर्थित नहीं है"))
आईओएस को https पर सेवा देने के लिए कार्डडीएवी सर्वर की आवश्यकता होती है। आप http.ListenAndServeTLS(addr, "localhost.crt", "localhost.key", NewCardDAVHandler())
openssl req -new -subj "/C=US/ST=Utah/CN=192.168.XXX.XXX" -newkey rsa:2048 -nodes -keyout localhost.key -out localhost.csr openssl x509 -req -days 365 -in localhost.csr -signkey localhost.key -out localhost.crt
उसके बाद आपको अपने स्वयं के आईपी-पते और पोर्ट की ओर इशारा करते हुए एक "कार्डडीएवी संपर्क खाता" जोड़कर स्थानीय रूप से प्रयोग करने में सक्षम होना चाहिए।
गो में कार्डडीएवी सर्वर को लागू करना थोड़ा जटिल है, लेकिन स्पष्ट रूप से इसके लायक है: आपके संपर्क स्वचालित रूप से आपके संगठन के सर्वर पर मौजूद डेटा के साथ सिंक हो जाएंगे!
क्या आप अन्य अच्छे प्रोटोकॉल जानते हैं जो इस तरह के मूल एकीकरण की अनुमति देते हैं? बेझिझक अपने अनुभव साझा करें!
अस्वीकरण: उपलब्ध कराए गए सभी संसाधन आंशिक रूप से इंटरनेट से हैं। यदि आपके कॉपीराइट या अन्य अधिकारों और हितों का कोई उल्लंघन होता है, तो कृपया विस्तृत कारण बताएं और कॉपीराइट या अधिकारों और हितों का प्रमाण प्रदान करें और फिर इसे ईमेल पर भेजें: [email protected] हम इसे आपके लिए यथाशीघ्र संभालेंगे।
Copyright© 2022 湘ICP备2022001581号-3